From e0870a72aca7b2b1bb43f945218559ee32e478be Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 12 Jun 2019 17:42:25 +0800 Subject: [PATCH 1/7] Add support as9716 platform --- platform/broadcom/one-image.mk | 1 + platform/broadcom/platform-modules-accton.mk | 6 + .../as9716-32d/classes/__init__.py | 0 .../as9716-32d/classes/fanutil.py | 251 +++++ .../as9716-32d/classes/thermalutil.py | 135 +++ .../as9716-32d/modules/Makefile | 19 + .../modules/accton_as9716_32d_cpld.c | 900 ++++++++++++++++++ .../modules/accton_as9716_32d_fan.c | 760 +++++++++++++++ .../modules/accton_as9716_32d_leds.c | 492 ++++++++++ .../modules/accton_as9716_32d_psu.c | 311 ++++++ .../as9716-32d/modules/accton_i2c_psu.c | 602 ++++++++++++ .../as9716-32d-platform-monitor-fan.service | 16 + .../as9716-32d-platform-monitor-psu.service | 16 + .../as9716-32d-platform-monitor.service | 18 + .../as9716-32d/setup.py | 16 + .../as9716-32d/utils/README | 117 +++ .../utils/accton_as9716_32d_monitor.py | 344 +++++++ .../utils/accton_as9716_32d_monitor_fan.py | 197 ++++ .../utils/accton_as9716_32d_monitor_psu.py | 169 ++++ .../utils/accton_as9716_32d_util.py | 571 +++++++++++ .../debian/control | 7 +- .../debian/rules | 2 +- 22 files changed, 4948 insertions(+), 2 deletions(-) create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index db9acc0cc30a..d17dcfe067d7 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -26,6 +26,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_MINIPACK_PLATFORM_MODULE) \ $(ACCTON_AS5812_54X_PLATFORM_MODULE) \ $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ + $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index 49be5781c8f0..ebf76bbd716d 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -13,6 +13,7 @@ ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1 ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -27,6 +28,7 @@ export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton @@ -83,4 +85,8 @@ ACCTON_AS5835_54X_PLATFORM_MODULE = sonic-platform-accton-as5835-54x_$(ACCTON_AS $(ACCTON_AS5835_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54x-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54X_PLATFORM_MODULE))) +ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE))) + SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py new file mode 100755 index 000000000000..ca0f3f9da1e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 12/03/2018: Jostar modify for as7726_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py new file mode 100755 index 000000000000..00c9950d52b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/18/2018:Jostar craete for as9716_32d +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 8 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 + THERMAL_NUM_6_IDX = 6 # 6_ON_MAIN_BROAD. LM75 + THERMAL_NUM_7_IDX = 7 # 7_ON_MAIN_BROAD. LM75 + THERMAL_NUM_8_IDX = 8 # 8_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['18', '48'], + THERMAL_NUM_2_IDX: ['18', '49'], + THERMAL_NUM_3_IDX: ['18', '4a'], + THERMAL_NUM_4_IDX: ['18', '4b'], + THERMAL_NUM_5_IDX: ['18', '4c'], + THERMAL_NUM_6_IDX: ['18', '4e'], + THERMAL_NUM_7_IDX: ['18', '4f'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/18-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_7_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_8_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], + } + + #def __init__(self): + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) + print "termal5=%d" %thermal._get_thermal_val(5) + print "termal7=%d" %thermal._get_thermal_val(6) + print "termal8=%d" %thermal._get_thermal_val(7) + print "termal9=%d" %thermal._get_thermal_val(8) + +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile new file mode 100755 index 000000000000..be04fc82cb59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as9716_32d_cpld.o accton_as9716_32d_fan.o \ + accton_as9716_32d_leds.o accton_as9716_32d_psu.o accton_i2c_psu.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-8-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd *.mod.c .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c new file mode 100755 index 000000000000..874bdc33bea4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c @@ -0,0 +1,900 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as9716_32d CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as9716_32d_fpga, + as9716_32d_cpld1, + as9716_32d_cpld2, + as9716_32d_cpld_cpu +}; + +struct as9716_32d_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as9716_32d_cpld_id[] = { + { "as9716_32d_fpga", as9716_32d_fpga }, + { "as9716_32d_cpld1", as9716_32d_cpld1 }, + { "as9716_32d_cpld2", as9716_32d_cpld2 }, + { "as9716_32d_cpld_cpu", as9716_32d_cpld_cpu }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as9716_32d_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + + +static struct attribute *as9716_32d_fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9716_32d_fpga_group = { + .attrs = as9716_32d_fpga_attributes, +}; + +static struct attribute *as9716_32d_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + NULL +}; + +static const struct attribute_group as9716_32d_cpld1_group = { + .attrs = as9716_32d_cpld1_attributes, +}; + +static struct attribute *as9716_32d_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as9716_32d_cpld2_group = { + .attrs = as9716_32d_cpld2_attributes, +}; + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x20; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x20; + mask = 0x8; + break; + case MODULE_RXLOS_33: + reg = 0x20; + mask = 0x2; + break; + case MODULE_RXLOS_34: + reg = 0x20; + mask = 0x10; + break; + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as9716_32d_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as9716_32d_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as9716_32d_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as9716_32d_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +/* + * I2C init/probing/exit functions + */ +static int as9716_32d_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as9716_32d_cpld_data *data; + int ret = -ENODEV; + int status; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as9716_32d_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + + /* Register sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + case as9716_32d_cpld_cpu: + /* Disable CPLD reset to avoid DUT will be reset. + */ + status=as9716_32d_cpld_write_internal(client, 0x3, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpu_cpld reg 0x65 err %d\n", status); + } + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as9716_32d_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as9716_32d_cpld_remove(struct i2c_client *client) +{ + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as9716_32d_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_read); + +int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_write); + +static struct i2c_driver as9716_32d_cpld_driver = { + .driver = { + .name = "as9716_32d_cpld", + .owner = THIS_MODULE, + }, + .probe = as9716_32d_cpld_probe, + .remove = as9716_32d_cpld_remove, + .id_table = as9716_32d_cpld_id, +}; + +static int __init as9716_32d_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as9716_32d_cpld_driver); +} + +static void __exit as9716_32d_cpld_exit(void) +{ + i2c_del_driver(&as9716_32d_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as9716_32d_cpld_init); +module_exit(as9716_32d_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c new file mode 100755 index 000000000000..4d2433e7981e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c @@ -0,0 +1,760 @@ +/* + * A hwmon driver for the Accton as9716 32d fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9716_32d_fan" + +#define NUM_THERMAL_SENSORS (7) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4c , 0x4e} + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as9716_32d_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) + +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); + +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as9716_32d_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as9716_32d_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as9716_32d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as9716_32d_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as9716_32d_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as9716_32d_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as9716_32d_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as9716_32d_fan_group = { + .attrs = as9716_32d_fan_attributes, +}; + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as9716_32d_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as9716_32d_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as9716_32d_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_fan_remove(struct i2c_client *client) +{ + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as9716_32d_fan_id[] = { + { "as9716_32d_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_fan_id); + +static struct i2c_driver as9716_32d_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as9716_32d_fan_probe, + .remove = as9716_32d_fan_remove, + .id_table = as9716_32d_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as9716_32d_fan_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c new file mode 100755 index 000000000000..0fd28a4631b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c @@ -0,0 +1,492 @@ +/* + * A LED driver for the accton_as9716_32d_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as9716_32d_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_as9716_32d_led" + +struct accton_as9716_32d_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* only 1 register*/ +}; + +static struct accton_as9716_32d_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x61) + +#define LED_TYPE_DIAG_REG_MASK (0x1|0x2|0x4) +#define LED_MODE_DIAG_GREEN_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x02) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0) + + +#define LED_TYPE_LOC_REG_MASK (0x80|0x40) +#define LED_MODE_LOC_GREEN_BLIKN_VALUE 0x80 +#define LED_MODE_LOC_AMBER_VALUE 0x40 +#define LED_MODE_LOC_OFF_VALUE (0x0) + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_AMBER_VALUE 0x20 +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) +#define LED_MODE_PSU2_AMBER_VALUE 0x8 +#define LED_MODE_PSU2_GREEN_VALUE 0x4 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) +#define LED_MODE_PSU1_AMBER_VALUE 0x2 +#define LED_MODE_PSU1_GREEN_VALUE 0x1 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as9716_32d_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as9716_32d_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as9716_32d_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as9716_32d_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_as9716_32d_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as9716_32d_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as9716_32d_led_diag_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as9716_32d_led_loc_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_as9716_32d_led_fan_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_as9716_32d_led_psu1_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_as9716_32d_led_psu2_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static struct led_classdev accton_as9716_32d_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as9716_32d_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_diag_set, + .brightness_get = accton_as9716_32d_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "accton_as9716_32d_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_loc_set, + .brightness_get = accton_as9716_32d_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "accton_as9716_32d_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_fan_set, + .brightness_get = accton_as9716_32d_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as9716_32d_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu1_set, + .brightness_get = accton_as9716_32d_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as9716_32d_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu2_set, + .brightness_get = accton_as9716_32d_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, +}; + +static int accton_as9716_32d_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_suspend(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_resume(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as9716_32d_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as9716_32d_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + } + + return ret; +} + +static int accton_as9716_32d_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as9716_32d_led_driver = { + .probe = accton_as9716_32d_led_probe, + .remove = accton_as9716_32d_led_remove, + .suspend = accton_as9716_32d_led_suspend, + .resume = accton_as9716_32d_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as9716_32d_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as9716_32d_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as9716_32d_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as9716_32d_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as9716_32d_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); +} + +module_init(accton_as9716_32d_led_init); +module_exit(accton_as9716_32d_led_exit); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("accton_as9716_32d_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c new file mode 100755 index 000000000000..06e8e23c3c53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c @@ -0,0 +1,311 @@ +/* + * An hwmon driver for accton as9716_32d Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as9716_32d_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER]; +}; + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev); + +enum as9716_32d_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as9716_32d_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as9716_32d_psu_group = { + .attrs = as9716_32d_psu_attributes, +}; + +static int as9716_32d_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_psu_remove(struct i2c_client *client) +{ + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as9716_32d_psu1, + as9716_32d_psu2 +}; + +static const struct i2c_device_id as9716_32d_psu_id[] = { + { "as9716_32d_psu1", as9716_32d_psu1 }, + { "as9716_32d_psu2", as9716_32d_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_psu_id); + +static struct i2c_driver as9716_32d_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as9716_32d_psu", + }, + .probe = as9716_32d_psu_probe, + .remove = as9716_32d_psu_remove, + .id_table = as9716_32d_psu_id, + .address_list = normal_i2c, +}; + +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as9716_32d update\n"); + + /* Read psu status */ + status = as9716_32d_cpld_read(0x60, 0x3); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as9716_32d_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as9716_32d_psu_read_block(client, 0x2e,data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as9716_32d_psu_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c new file mode 100755 index 000000000000..df7324de5604 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c @@ -0,0 +1,602 @@ +/* + * An hwmon driver for the Accton Redundant Power Module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" +/* PMBus Protocol. */ +#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 +#define PMBUS_REGISTER_VOUT_MODE 0x20 +#define PMBUS_REGISTER_STATUS_BYTE 0x78 +#define PMBUS_REGISTER_STATUS_WORD 0x79 +#define PMBUS_REGISTER_STATUS_FAN 0x81 +#define PMBUS_REGISTER_READ_VIN 0x88 +#define PMBUS_REGISTER_READ_IIN 0x89 +#define PMBUS_REGISTER_READ_VOUT 0x8B +#define PMBUS_REGISTER_READ_IOUT 0x8C +#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D +#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E +#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F +#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 +#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 + +#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A +#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B + +#define PMBUS_REGISTER_READ_POUT 0x96 +#define PMBUS_REGISTER_READ_PIN 0x97 +#define PMBUS_REGISTER_MFR_ID 0x99 +#define PMBUS_REGISTER_MFR_MODEL 0x9A +#define PMBUS_REGISTER_MFR_REVISION 0x9B +#define PMBUS_REGISTER_MFR_SERIAL 0x9E + + +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct accton_i2c_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u8 mfr_serial[26]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); + +enum accton_i2c_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT_UV, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_SERIAL, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +//static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + + +static struct attribute *accton_i2c_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + //&sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 0; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier=1; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + if(!multiplier) + multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; + if(attr->index==PSU_P_OUT_UV) + multiplier = 1000000; + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + int exponent, mantissa; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : + sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); +} + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + switch (attr->index) { + + case PSU_MFR_ID: + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: + ptr = data->mfr_revsion; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + + +static const struct attribute_group accton_i2c_psu_group = { + .attrs = accton_i2c_psu_attributes, +}; + +static int accton_i2c_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct accton_i2c_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int accton_i2c_psu_remove(struct i2c_client *client) +{ + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); + kfree(data); + + return 0; +} +/* Support psu moduel + */ +static const struct i2c_device_id accton_i2c_psu_id[] = { + { "acbel_fsh082", 0 }, + { "yesm1300am", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); + +static struct i2c_driver accton_i2c_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_psu", + }, + .probe = accton_i2c_psu_probe, + .remove = accton_i2c_psu_remove, + .id_table = accton_i2c_psu_id, + .address_list = normal_i2c, +}; + +static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) +{ + int status = -EIO; + int length; + u8 buffer[128] = {0}, *ptr = buffer; + + status = accton_i2c_psu_read_byte(client, command); + if (status < 0) + { + dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + + status = (status & 0xFF) + 1; + if ( status > 128) + { + dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); + status = -EINVAL; + goto EXIT_READ_BLOCK_DATA; + } + + length = status; + status = accton_i2c_psu_read_block(client, command, buffer, length); + if (unlikely(status < 0)) + goto EXIT_READ_BLOCK_DATA; + if (unlikely(status != length)) { + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + /* The first byte is the count byte of string. */ + ptr++; + status--; + + length=status>(data_length-1)?(data_length-1):status; + memcpy(data, ptr, length); + data[length-1] = 0; + +EXIT_READ_BLOCK_DATA: + + return status; +} + + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + //u8 command, buf; + struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, + {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, + {PMBUS_REGISTER_READ_VOUT, &data->v_out}, + {PMBUS_REGISTER_READ_IIN, &data->i_in}, + {PMBUS_REGISTER_READ_IOUT, &data->i_out}, + {PMBUS_REGISTER_READ_POUT, &data->p_out}, + {PMBUS_REGISTER_READ_PIN, &data->p_in}, + {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, + {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, + {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, + }; + + dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = accton_i2c_psu_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + + } + /* Read mfr_id */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, + ARRAY_SIZE(data->mfr_id)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); + goto exit; + } + /* Read mfr_model */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, + ARRAY_SIZE(data->mfr_model)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); + goto exit; + } + /* Read mfr_revsion */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); + goto exit; + } + /* Read mfr_serial */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, + ARRAY_SIZE(data->mfr_serial)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init accton_i2c_psu_init(void) +{ + return i2c_add_driver(&accton_i2c_psu_driver); +} + +static void __exit accton_i2c_psu_exit(void) +{ + i2c_del_driver(&accton_i2c_psu_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_psu_init); +module_exit(accton_i2c_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service new file mode 100755 index 000000000000..b77b40d67299 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring FAN service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service new file mode 100755 index 000000000000..69bcf37e27f5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring PSU service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service new file mode 100755 index 000000000000..1d77c39120a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as9716_32d_util.py install +ExecStart=/usr/local/bin/accton_as9716_32d_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py new file mode 100755 index 000000000000..7c70492e5d6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as9716_32d', + version='1.0', + description='Module to initialize Accton AS9716-32D platforms', + + packages=['as9716_32d'], + package_dir={'as9716_32d': 'as9716-32d/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program 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, either version 3 of the License, or +(at your option) any later version. + +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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py new file mode 100755 index 000000000000..f80c1223a83c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 12/19/2018:Jostar create for as9716_32d thermal plan +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as9716_32d.fanutil import FanUtil + from as9716_32d.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32x_monitor' + +global log_file +global log_level + + +# Air Flow Front to Back : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system +# One Fan fail : Change Fan speed to 100%(0x0E) + + +# Air Flow Back to Front : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system +# One Fan fail: Change Fan speed to 100%(0x0E) +# sensor_LM75_CPU == sensor_LM75_4B + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] +temp_test_data=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2]) + if temp > policy[i][2]: + if temp <= policy[i][3]: + state =i + logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) + logging.debug ('fan_state=%d', state) + break + + return state + + + def manage_fans(self): + + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + global temp_test_data + + LEVEL_FAN_DEF=0 + LEVEL_FAN_MID=1 + LEVEL_FAN_MAX=2 + LEVEL_TEMP_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + + + fan_policy_f2b = { + LEVEL_FAN_DEF: [38, 0x4, 0, 38000], + LEVEL_FAN_MID: [63, 0x6, 38000, 46000], + LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], + LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], + } + fan_policy_b2f = { + LEVEL_FAN_DEF: [38, 0x4, 0, 34000], + LEVEL_FAN_MID: [63, 0x8, 34000, 44000], + LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], + LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], + } + + fan_policy = fan_policy_f2b + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_dri=1 #something wrong, set fan_dir to default val + else: + fan_policy = fan_policy_b2f + + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + fan_fail=0 + + if temp3==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp4==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 + ori_state=fan_policy_state + + #temp_test_data=temp_test_data+1000 + #temp_get = temp_get + temp_test_data + #print "Unit test:temp_get=%d"%temp_get + + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + #print "temp3=%d"%temp3 + #print "temp4=%d"%temp4 + #print "temp_get=%d"%temp_get + + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_fan_cycle=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + #if fan_policy_state == ori_state: + # return True + #else: + new_state = fan_policy_state + + #logging.warning('Temperature high alarm testing') + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=7: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 7): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + #monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py new file mode 100755 index 000000000000..320655361b83 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/13/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/17-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py new file mode 100755 index 000000000000..a8df99430c81 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/12/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "9-0050", + 1: "10-0051", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py new file mode 100755 index 000000000000..e9779db01d2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py @@ -0,0 +1,571 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as9716_32d' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':34} + + +led_prefix ='/sys/devices/platform/as9716_32d_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as9716_32d_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + 'fan6': ['fan_duty_cycle_percentage','fan6_fault', 'fan6_speed_rpm', 'fan6_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['18-0048', '18-0049','18-004a', '18-004b', '18-004c', '18-004e', '18-004f'] , + 'psu': ['9-0058', '10-0059'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58] + +#sfp_map = [25, 26] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', + +'echo as9716_32d_fpga 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo as9716_32d_cpld1 0x61 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo as9716_32d_cpld2 0x62 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as9716_32d_cpld_cpu 0x65 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as9716_32d_fan 0x66 > /sys/bus/i2c/devices/i2c-17/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4f > /sys/bus/i2c/devices/i2c-18/new_device', + +# PSU-1 +'echo as9716_32d_psu1 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo acbel_fsh082 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', + +# PSU-2 +'echo as9716_32d_psu2 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo acbel_fsh082 0x59 > /sys/bus/i2c/devices/i2c-10/new_device', + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) > DEVICE_NO['sfp'] -1: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_psu', +'modprobe accton_as9716_32d_cpld', +'modprobe accton_as9716_32d_fan', +'modprobe accton_as9716_32d_leds', +'modprobe accton_as9716_32d_psu', +'modprobe optoe', +'modprobe lm75'] + +cpld_reset_stop='i2cset -y 0 0x65 0x3 0x0' + +def driver_install(): + + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + log_os_system(cpld_reset_stop, 1) + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + print "init i2c device instance" + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + #if len(ALL_DEVICE)==0: + # devices_info() + #node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + #node = node.replace(node.split("/")[-1], 'eeprom') + node= "/sys/bus/i2c/devices/"+str(sfp_map[int(index)])+"-0050" + "/eeprom" + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + #print node + ":" + #ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + ret, log = log_os_system(hex_cmd+" -C " + node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index e6249a6a2c71..b22828af67c5 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -1,7 +1,7 @@ Source: sonic-accton-platform-modules Section: main Priority: extra -Maintainer: Accton network , Accton Network +Maintainer: Accton network , Accton Network , Accton Network Build-Depends: debhelper (>= 9), bzip2 Standards-Version: 3.9.3 @@ -56,3 +56,8 @@ Description: kernel modules for platform devices such as fan, led, sfp Package: sonic-platform-accton-as5835-54x Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as9716-32d +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index 5eecf73139e4..46014874d5c0 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x +MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service From 797348550086bed55a455e35c95343a9dbe93b73 Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 12 Jun 2019 17:55:57 +0800 Subject: [PATCH 2/7] remove as9716 --- .../as9716-32d/classes/__init__.py | 0 .../as9716-32d/classes/fanutil.py | 251 ----- .../as9716-32d/classes/thermalutil.py | 135 --- .../as9716-32d/modules/Makefile | 19 - .../modules/accton_as9716_32d_cpld.c | 900 ------------------ .../modules/accton_as9716_32d_fan.c | 760 --------------- .../modules/accton_as9716_32d_leds.c | 492 ---------- .../modules/accton_as9716_32d_psu.c | 311 ------ .../as9716-32d/modules/accton_i2c_psu.c | 602 ------------ .../as9716-32d-platform-monitor-fan.service | 16 - .../as9716-32d-platform-monitor-psu.service | 16 - .../as9716-32d-platform-monitor.service | 18 - .../as9716-32d/setup.py | 16 - .../as9716-32d/utils/README | 117 --- .../utils/accton_as9716_32d_monitor.py | 344 ------- .../utils/accton_as9716_32d_monitor_fan.py | 197 ---- .../utils/accton_as9716_32d_monitor_psu.py | 169 ---- .../utils/accton_as9716_32d_util.py | 571 ----------- 18 files changed, 4934 deletions(-) delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py delete mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py deleted file mode 100755 index e69de29bb2d1..000000000000 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py deleted file mode 100755 index ca0f3f9da1e3..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2017 Accton Technology Corporation -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# mm/dd/yyyy (A.D.) -# 11/13/2017: Polly Hsu, Create -# 1/10/2018: Jostar modify for as7716_32 -# 12/03/2018: Jostar modify for as7726_32 -# ------------------------------------------------------------------ - -try: - import time - import logging - from collections import namedtuple -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - - -class FanUtil(object): - """Platform-specific FanUtil class""" - - FAN_NUM_ON_MAIN_BROAD = 6 - FAN_NUM_1_IDX = 1 - FAN_NUM_2_IDX = 2 - FAN_NUM_3_IDX = 3 - FAN_NUM_4_IDX = 4 - FAN_NUM_5_IDX = 5 - FAN_NUM_6_IDX = 6 - - FAN_NODE_NUM_OF_MAP = 2 - FAN_NODE_FAULT_IDX_OF_MAP = 1 - FAN_NODE_DIR_IDX_OF_MAP = 2 - - BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' - FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' - - #logfile = '' - #loglevel = logging.INFO - - """ Dictionary where - key1 = fan id index (integer) starting from 1 - key2 = fan node index (interger) starting from 1 - value = path to fan device file (string) """ - _fan_to_device_path_mapping = {} - -#fan1_direction -#fan1_fault -#fan1_present - - #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', - _fan_to_device_node_mapping = { - (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', - (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', - - (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', - (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', - - (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', - (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', - - (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', - (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', - - (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', - (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', - - (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', - (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', - } - - def _get_fan_to_device_node(self, fan_num, node_num): - return self._fan_to_device_node_mapping[(fan_num, node_num)] - - def _get_fan_node_val(self, fan_num, node_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) - return None - - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) - return None - - device_path = self.get_fan_to_device_path(fan_num, node_num) - - try: - val_file = open(device_path, 'r') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None - - content = val_file.readline().rstrip() - - if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) - return None - - try: - val_file.close() - except: - logging.debug('GET. unable to close file. device_path:%s', device_path) - return None - - return int(content) - - def _set_fan_node_val(self, fan_num, node_num, val): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) - return None - - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) - return None - - content = str(val) - if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) - return None - - device_path = self.get_fan_to_device_path(fan_num, node_num) - try: - val_file = open(device_path, 'w') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None - - val_file.write(content) - - try: - val_file.close() - except: - logging.debug('GET. unable to close file. device_path:%s', device_path) - return None - - return True - - def __init__(self): - fan_path = self.BASE_VAL_PATH - - for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): - for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): - self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( - self._fan_to_device_node_mapping[(fan_num, node_num)]) - - def get_num_fans(self): - return self.FAN_NUM_ON_MAIN_BROAD - - def get_idx_fan_start(self): - return self.FAN_NUM_1_IDX - - def get_num_nodes(self): - return self.FAN_NODE_NUM_OF_MAP - - def get_idx_node_start(self): - return self.FAN_NODE_FAULT_IDX_OF_MAP - - def get_size_node_map(self): - return len(self._fan_to_device_node_mapping) - - def get_size_path_map(self): - return len(self._fan_to_device_path_mapping) - - def get_fan_to_device_path(self, fan_num, node_num): - return self._fan_to_device_path_mapping[(fan_num, node_num)] - - def get_fan_fault(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) - - #def get_fan_speed(self, fan_num): - # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) - - def get_fan_dir(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) - - def get_fan_duty_cycle(self): - #duty_path = self.FAN_DUTY_PATH - try: - val_file = open(self.FAN_DUTY_PATH) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - - content = val_file.readline().rstrip() - val_file.close() - - return int(content) - #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) -#static u32 reg_val_to_duty_cycle(u8 reg_val) -#{ -# reg_val &= FAN_DUTY_CYCLE_REG_MASK; -# return ((u32)(reg_val+1) * 625 + 75)/ 100; -#} -# - def set_fan_duty_cycle(self, val): - - try: - fan_file = open(self.FAN_DUTY_PATH, 'r+') - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - #val = ((val + 1 ) * 625 +75 ) / 100 - fan_file.write(str(val)) - fan_file.close() - return True - - #def get_fanr_fault(self, fan_num): - # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) - - def get_fanr_speed(self, fan_num): - return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) - - def get_fan_status(self, fan_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num, %d', fan_num) - return None - - if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: - logging.debug('GET. FAN fault. fan_num, %d', fan_num) - return False - - #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: - # logging.debug('GET. FANR fault. fan_num, %d', fan_num) - # return False - - return True - -#def main(): -# fan = FanUtil() -# -# print 'get_size_node_map : %d' % fan.get_size_node_map() -# print 'get_size_path_map : %d' % fan.get_size_path_map() -# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): -# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): -# print fan.get_fan_to_device_path(x, y) -# -#if __name__ == '__main__': -# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py deleted file mode 100755 index 00c9950d52b6..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2017 Accton Technology Corporation -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# mm/dd/yyyy (A.D.) -# 12/18/2018:Jostar craete for as9716_32d -# ------------------------------------------------------------------ - -try: - import os - import time - import logging - import glob - import commands - from collections import namedtuple -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - -class ThermalUtil(object): - """Platform-specific ThermalUtil class""" - THERMAL_NUM_MAX = 8 - THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 - THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 - THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 - THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 - THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 - THERMAL_NUM_6_IDX = 6 # 6_ON_MAIN_BROAD. LM75 - THERMAL_NUM_7_IDX = 7 # 7_ON_MAIN_BROAD. LM75 - THERMAL_NUM_8_IDX = 8 # 8_ON_MAIN_BROAD. LM75 - - """ Dictionary where - key1 = thermal id index (integer) starting from 1 - value = path to fan device file (string) """ - #_thermal_to_device_path_mapping = {} - - _thermal_to_device_node_mapping = { - THERMAL_NUM_1_IDX: ['18', '48'], - THERMAL_NUM_2_IDX: ['18', '49'], - THERMAL_NUM_3_IDX: ['18', '4a'], - THERMAL_NUM_4_IDX: ['18', '4b'], - THERMAL_NUM_5_IDX: ['18', '4c'], - THERMAL_NUM_6_IDX: ['18', '4e'], - THERMAL_NUM_7_IDX: ['18', '4f'], - } - thermal_sysfspath ={ - THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-0048/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/18-0049/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_7_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"], - THERMAL_NUM_8_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], - } - - #def __init__(self): - - def _get_thermal_val(self, thermal_num): - if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: - logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) - return None - - device_path = self.get_thermal_to_device_path(thermal_num) - for filename in glob.glob(device_path): - try: - val_file = open(filename, 'r') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None - content = val_file.readline().rstrip() - if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) - return None - try: - val_file.close() - except: - logging.debug('GET. unable to close file. device_path:%s', device_path) - return None - - return int(content) - - return 0 - - def get_num_thermals(self): - return self.THERMAL_NUM_MAX - - def get_idx_thermal_start(self): - return self.THERMAL_NUM_1_IDX - - def get_size_node_map(self): - return len(self._thermal_to_device_node_mapping) - - def get_size_path_map(self): - return len(self.thermal_sysfspath) - - def get_thermal_to_device_path(self, thermal_num): - return self.thermal_sysfspath[thermal_num][0] - - def get_thermal_temp(self): - return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) - -def main(): - thermal = ThermalUtil() - print "termal1=%d" %thermal._get_thermal_val(1) - print "termal2=%d" %thermal._get_thermal_val(2) - print "termal3=%d" %thermal._get_thermal_val(3) - print "termal4=%d" %thermal._get_thermal_val(4) - print "termal5=%d" %thermal._get_thermal_val(5) - print "termal7=%d" %thermal._get_thermal_val(6) - print "termal8=%d" %thermal._get_thermal_val(7) - print "termal9=%d" %thermal._get_thermal_val(8) - -# -# print 'get_size_node_map : %d' % thermal.get_size_node_map() -# print 'get_size_path_map : %d' % thermal.get_size_path_map() -# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): -# print thermal.get_thermal_to_device_path(x) -# -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile deleted file mode 100755 index be04fc82cb59..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -ifneq ($(KERNELRELEASE),) -obj-m:= accton_as9716_32d_cpld.o accton_as9716_32d_fan.o \ - accton_as9716_32d_leds.o accton_as9716_32d_psu.o accton_i2c_psu.o - -else -ifeq (,$(KERNEL_SRC)) -#$(error KERNEL_SRC is not defined) -KVERSION=3.16.0-8-amd64 -KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ -KERNELDIR:=$(KERNEL_DIR) -else -KERNELDIR:=$(KERNEL_SRC) -endif -PWD:=$(shell pwd) -default: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules -clean: - rm -rf *.o *.mod.o *.mod.o *.ko .*cmd *.mod.c .tmp_versions Module.markers Module.symvers modules.order -endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c deleted file mode 100755 index 874bdc33bea4..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c +++ /dev/null @@ -1,900 +0,0 @@ -/* - * Copyright (C) Brandon Chuang - * - * This module supports the accton cpld that hold the channel select - * mechanism for other i2c slave devices, such as SFP. - * This includes the: - * Accton as9716_32d CPLD1/CPLD2/CPLD3 - * - * Based on: - * pca954x.c from Kumar Gala - * Copyright (C) 2006 - * - * Based on: - * pca954x.c from Ken Harrenstien - * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) - * - * Based on: - * i2c-virtual_cb.c from Brian Kuschak - * and - * pca9540.c from Jean Delvare . - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -static LIST_HEAD(cpld_client_list); -static struct mutex list_lock; - -struct cpld_client_node { - struct i2c_client *client; - struct list_head list; -}; - -enum cpld_type { - as9716_32d_fpga, - as9716_32d_cpld1, - as9716_32d_cpld2, - as9716_32d_cpld_cpu -}; - -struct as9716_32d_cpld_data { - enum cpld_type type; - struct device *hwmon_dev; - struct mutex update_lock; -}; - -static const struct i2c_device_id as9716_32d_cpld_id[] = { - { "as9716_32d_fpga", as9716_32d_fpga }, - { "as9716_32d_cpld1", as9716_32d_cpld1 }, - { "as9716_32d_cpld2", as9716_32d_cpld2 }, - { "as9716_32d_cpld_cpu", as9716_32d_cpld_cpu }, - { } -}; -MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id); - -#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index -#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index -#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index -#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index -#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index - -enum as9716_32d_cpld_sysfs_attributes { - CPLD_VERSION, - ACCESS, - /* transceiver attributes */ - TRANSCEIVER_PRESENT_ATTR_ID(1), - TRANSCEIVER_PRESENT_ATTR_ID(2), - TRANSCEIVER_PRESENT_ATTR_ID(3), - TRANSCEIVER_PRESENT_ATTR_ID(4), - TRANSCEIVER_PRESENT_ATTR_ID(5), - TRANSCEIVER_PRESENT_ATTR_ID(6), - TRANSCEIVER_PRESENT_ATTR_ID(7), - TRANSCEIVER_PRESENT_ATTR_ID(8), - TRANSCEIVER_PRESENT_ATTR_ID(9), - TRANSCEIVER_PRESENT_ATTR_ID(10), - TRANSCEIVER_PRESENT_ATTR_ID(11), - TRANSCEIVER_PRESENT_ATTR_ID(12), - TRANSCEIVER_PRESENT_ATTR_ID(13), - TRANSCEIVER_PRESENT_ATTR_ID(14), - TRANSCEIVER_PRESENT_ATTR_ID(15), - TRANSCEIVER_PRESENT_ATTR_ID(16), - TRANSCEIVER_PRESENT_ATTR_ID(17), - TRANSCEIVER_PRESENT_ATTR_ID(18), - TRANSCEIVER_PRESENT_ATTR_ID(19), - TRANSCEIVER_PRESENT_ATTR_ID(20), - TRANSCEIVER_PRESENT_ATTR_ID(21), - TRANSCEIVER_PRESENT_ATTR_ID(22), - TRANSCEIVER_PRESENT_ATTR_ID(23), - TRANSCEIVER_PRESENT_ATTR_ID(24), - TRANSCEIVER_PRESENT_ATTR_ID(25), - TRANSCEIVER_PRESENT_ATTR_ID(26), - TRANSCEIVER_PRESENT_ATTR_ID(27), - TRANSCEIVER_PRESENT_ATTR_ID(28), - TRANSCEIVER_PRESENT_ATTR_ID(29), - TRANSCEIVER_PRESENT_ATTR_ID(30), - TRANSCEIVER_PRESENT_ATTR_ID(31), - TRANSCEIVER_PRESENT_ATTR_ID(32), - TRANSCEIVER_PRESENT_ATTR_ID(33), - TRANSCEIVER_PRESENT_ATTR_ID(34), - TRANSCEIVER_TXDISABLE_ATTR_ID(33), - TRANSCEIVER_TXDISABLE_ATTR_ID(34), - TRANSCEIVER_RXLOS_ATTR_ID(33), - TRANSCEIVER_RXLOS_ATTR_ID(34), - TRANSCEIVER_TXFAULT_ATTR_ID(33), - TRANSCEIVER_TXFAULT_ATTR_ID(34), - TRANSCEIVER_RESET_ATTR_ID(1), - TRANSCEIVER_RESET_ATTR_ID(2), - TRANSCEIVER_RESET_ATTR_ID(3), - TRANSCEIVER_RESET_ATTR_ID(4), - TRANSCEIVER_RESET_ATTR_ID(5), - TRANSCEIVER_RESET_ATTR_ID(6), - TRANSCEIVER_RESET_ATTR_ID(7), - TRANSCEIVER_RESET_ATTR_ID(8), - TRANSCEIVER_RESET_ATTR_ID(9), - TRANSCEIVER_RESET_ATTR_ID(10), - TRANSCEIVER_RESET_ATTR_ID(11), - TRANSCEIVER_RESET_ATTR_ID(12), - TRANSCEIVER_RESET_ATTR_ID(13), - TRANSCEIVER_RESET_ATTR_ID(14), - TRANSCEIVER_RESET_ATTR_ID(15), - TRANSCEIVER_RESET_ATTR_ID(16), - TRANSCEIVER_RESET_ATTR_ID(17), - TRANSCEIVER_RESET_ATTR_ID(18), - TRANSCEIVER_RESET_ATTR_ID(19), - TRANSCEIVER_RESET_ATTR_ID(20), - TRANSCEIVER_RESET_ATTR_ID(21), - TRANSCEIVER_RESET_ATTR_ID(22), - TRANSCEIVER_RESET_ATTR_ID(23), - TRANSCEIVER_RESET_ATTR_ID(24), - TRANSCEIVER_RESET_ATTR_ID(25), - TRANSCEIVER_RESET_ATTR_ID(26), - TRANSCEIVER_RESET_ATTR_ID(27), - TRANSCEIVER_RESET_ATTR_ID(28), - TRANSCEIVER_RESET_ATTR_ID(29), - TRANSCEIVER_RESET_ATTR_ID(30), - TRANSCEIVER_RESET_ATTR_ID(31), - TRANSCEIVER_RESET_ATTR_ID(32), -}; - -/* sysfs attributes for hwmon - */ -static ssize_t show_status(struct device *dev, struct device_attribute *da, - char *buf); -static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count); -static ssize_t access(struct device *dev, struct device_attribute *da, - const char *buf, size_t count); -static ssize_t show_version(struct device *dev, struct device_attribute *da, - char *buf); -static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, - char *buf); -static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, - const char *buf, size_t count); -static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg); -static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); - -/* transceiver attributes */ -#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ - static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) -#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr - -#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ - static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ - static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ - static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); - -#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ - &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ - &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ - &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr - -/*reset*/ -#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ - static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) -#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr - - - -static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); -static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); -/* transceiver attributes */ -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); -DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); -DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); -DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); -DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); - - - -static struct attribute *as9716_32d_fpga_attributes[] = { - &sensor_dev_attr_version.dev_attr.attr, - &sensor_dev_attr_access.dev_attr.attr, - NULL -}; - -static const struct attribute_group as9716_32d_fpga_group = { - .attrs = as9716_32d_fpga_attributes, -}; - -static struct attribute *as9716_32d_cpld1_attributes[] = { - &sensor_dev_attr_version.dev_attr.attr, - &sensor_dev_attr_access.dev_attr.attr, - DECLARE_TRANSCEIVER_PRESENT_ATTR(1), - DECLARE_TRANSCEIVER_PRESENT_ATTR(2), - DECLARE_TRANSCEIVER_PRESENT_ATTR(3), - DECLARE_TRANSCEIVER_PRESENT_ATTR(4), - DECLARE_TRANSCEIVER_PRESENT_ATTR(5), - DECLARE_TRANSCEIVER_PRESENT_ATTR(6), - DECLARE_TRANSCEIVER_PRESENT_ATTR(7), - DECLARE_TRANSCEIVER_PRESENT_ATTR(8), - DECLARE_TRANSCEIVER_PRESENT_ATTR(9), - DECLARE_TRANSCEIVER_PRESENT_ATTR(10), - DECLARE_TRANSCEIVER_PRESENT_ATTR(11), - DECLARE_TRANSCEIVER_PRESENT_ATTR(12), - DECLARE_TRANSCEIVER_PRESENT_ATTR(13), - DECLARE_TRANSCEIVER_PRESENT_ATTR(14), - DECLARE_TRANSCEIVER_PRESENT_ATTR(15), - DECLARE_TRANSCEIVER_PRESENT_ATTR(16), - DECLARE_TRANSCEIVER_RESET_ATTR(1), - DECLARE_TRANSCEIVER_RESET_ATTR(2), - DECLARE_TRANSCEIVER_RESET_ATTR(3), - DECLARE_TRANSCEIVER_RESET_ATTR(4), - DECLARE_TRANSCEIVER_RESET_ATTR(5), - DECLARE_TRANSCEIVER_RESET_ATTR(6), - DECLARE_TRANSCEIVER_RESET_ATTR(7), - DECLARE_TRANSCEIVER_RESET_ATTR(8), - DECLARE_TRANSCEIVER_RESET_ATTR(9), - DECLARE_TRANSCEIVER_RESET_ATTR(10), - DECLARE_TRANSCEIVER_RESET_ATTR(11), - DECLARE_TRANSCEIVER_RESET_ATTR(12), - DECLARE_TRANSCEIVER_RESET_ATTR(13), - DECLARE_TRANSCEIVER_RESET_ATTR(14), - DECLARE_TRANSCEIVER_RESET_ATTR(15), - DECLARE_TRANSCEIVER_RESET_ATTR(16), - NULL -}; - -static const struct attribute_group as9716_32d_cpld1_group = { - .attrs = as9716_32d_cpld1_attributes, -}; - -static struct attribute *as9716_32d_cpld2_attributes[] = { - &sensor_dev_attr_version.dev_attr.attr, - &sensor_dev_attr_access.dev_attr.attr, - DECLARE_TRANSCEIVER_PRESENT_ATTR(17), - DECLARE_TRANSCEIVER_PRESENT_ATTR(18), - DECLARE_TRANSCEIVER_PRESENT_ATTR(19), - DECLARE_TRANSCEIVER_PRESENT_ATTR(20), - DECLARE_TRANSCEIVER_PRESENT_ATTR(21), - DECLARE_TRANSCEIVER_PRESENT_ATTR(22), - DECLARE_TRANSCEIVER_PRESENT_ATTR(23), - DECLARE_TRANSCEIVER_PRESENT_ATTR(24), - DECLARE_TRANSCEIVER_PRESENT_ATTR(25), - DECLARE_TRANSCEIVER_PRESENT_ATTR(26), - DECLARE_TRANSCEIVER_PRESENT_ATTR(27), - DECLARE_TRANSCEIVER_PRESENT_ATTR(28), - DECLARE_TRANSCEIVER_PRESENT_ATTR(29), - DECLARE_TRANSCEIVER_PRESENT_ATTR(30), - DECLARE_TRANSCEIVER_PRESENT_ATTR(31), - DECLARE_TRANSCEIVER_PRESENT_ATTR(32), - DECLARE_TRANSCEIVER_PRESENT_ATTR(33), - DECLARE_TRANSCEIVER_PRESENT_ATTR(34), - DECLARE_SFP_TRANSCEIVER_ATTR(33), - DECLARE_SFP_TRANSCEIVER_ATTR(34), - DECLARE_TRANSCEIVER_RESET_ATTR(17), - DECLARE_TRANSCEIVER_RESET_ATTR(18), - DECLARE_TRANSCEIVER_RESET_ATTR(19), - DECLARE_TRANSCEIVER_RESET_ATTR(20), - DECLARE_TRANSCEIVER_RESET_ATTR(21), - DECLARE_TRANSCEIVER_RESET_ATTR(22), - DECLARE_TRANSCEIVER_RESET_ATTR(23), - DECLARE_TRANSCEIVER_RESET_ATTR(24), - DECLARE_TRANSCEIVER_RESET_ATTR(25), - DECLARE_TRANSCEIVER_RESET_ATTR(26), - DECLARE_TRANSCEIVER_RESET_ATTR(27), - DECLARE_TRANSCEIVER_RESET_ATTR(28), - DECLARE_TRANSCEIVER_RESET_ATTR(29), - DECLARE_TRANSCEIVER_RESET_ATTR(30), - DECLARE_TRANSCEIVER_RESET_ATTR(31), - DECLARE_TRANSCEIVER_RESET_ATTR(32), - NULL -}; - -static const struct attribute_group as9716_32d_cpld2_group = { - .attrs = as9716_32d_cpld2_attributes, -}; - - -static ssize_t show_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - int status = 0; - u8 reg = 0, mask = 0, revert = 0; - - switch (attr->index) { - case MODULE_PRESENT_1 ... MODULE_PRESENT_8: - reg = 0x12; - mask = 0x1 << (attr->index - MODULE_PRESENT_1); - break; - case MODULE_PRESENT_9 ... MODULE_PRESENT_16: - reg = 0x13; - mask = 0x1 << (attr->index - MODULE_PRESENT_9); - break; - case MODULE_PRESENT_17 ... MODULE_PRESENT_24: - reg = 0x12; - mask = 0x1 << (attr->index - MODULE_PRESENT_17); - break; - case MODULE_PRESENT_25 ... MODULE_PRESENT_32: - reg = 0x13; - mask = 0x1 << (attr->index - MODULE_PRESENT_25); - break; - case MODULE_PRESENT_33: - reg = 0x20; - mask = 0x1; - break; - case MODULE_PRESENT_34: - reg = 0x20; - mask = 0x8; - break; - case MODULE_RXLOS_33: - reg = 0x20; - mask = 0x2; - break; - case MODULE_RXLOS_34: - reg = 0x20; - mask = 0x10; - break; - case MODULE_TXDISABLE_33: - reg = 0x21; - mask = 0x1; - break; - case MODULE_TXDISABLE_34: - reg = 0x21; - mask = 0x2; - break; - - default: - return 0; - } - - if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { - revert = 1; - } - - mutex_lock(&data->update_lock); - status = as9716_32d_cpld_read_internal(client, reg); - if (unlikely(status < 0)) { - goto exit; - } - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); - -exit: - mutex_unlock(&data->update_lock); - return status; -} - -static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - long disable; - int status; - u8 reg = 0, mask = 0; - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - switch (attr->index) { - case MODULE_TXDISABLE_33: - reg = 0x21; - mask = 0x1; - break; - case MODULE_TXDISABLE_34: - reg = 0x21; - mask = 0x2; - break; - default: - return 0; - } - - /* Read current status */ - mutex_lock(&data->update_lock); - status = as9716_32d_cpld_read_internal(client, reg); - if (unlikely(status < 0)) { - goto exit; - } - - /* Update tx_disable status */ - if (disable) { - status |= mask; - } - else { - status &= ~mask; - } - - status = as9716_32d_cpld_write_internal(client, reg, status); - if (unlikely(status < 0)) { - goto exit; - } - - mutex_unlock(&data->update_lock); - return count; - -exit: - mutex_unlock(&data->update_lock); - return status; -} - -static ssize_t access(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - int status; - u32 addr, val; - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - - if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { - return -EINVAL; - } - - if (addr > 0xFF || val > 0xFF) { - return -EINVAL; - } - - mutex_lock(&data->update_lock); - status = as9716_32d_cpld_write_internal(client, addr, val); - if (unlikely(status < 0)) { - goto exit; - } - mutex_unlock(&data->update_lock); - return count; - -exit: - mutex_unlock(&data->update_lock); - return status; -} - -static void as9716_32d_cpld_add_client(struct i2c_client *client) -{ - struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); - - if (!node) { - dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); - return; - } - - node->client = client; - - mutex_lock(&list_lock); - list_add(&node->list, &cpld_client_list); - mutex_unlock(&list_lock); -} - -static void as9716_32d_cpld_remove_client(struct i2c_client *client) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int found = 0; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client == client) { - found = 1; - break; - } - } - - if (found) { - list_del(list_node); - kfree(cpld_node); - } - - mutex_unlock(&list_lock); -} - -static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) -{ - int val = 0; - struct i2c_client *client = to_i2c_client(dev); - - val = i2c_smbus_read_byte_data(client, 0x1); - - if (val < 0) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - int status = 0; - u8 reg = 0, mask = 0; - - switch (attr->index) { - case MODULE_RESET_1 ... MODULE_RESET_8: - reg = 0x14; - mask = 0x1 << (attr->index - MODULE_RESET_1); - break; - case MODULE_RESET_9 ... MODULE_RESET_16: - reg = 0x15; - mask = 0x1 << (attr->index - MODULE_RESET_9); - break; - case MODULE_RESET_17 ... MODULE_RESET_24: - reg = 0x14; - mask = 0x1 << (attr->index - MODULE_RESET_17); - break; - case MODULE_RESET_25 ... MODULE_RESET_32: - reg = 0x15; - mask = 0x1 << (attr->index - MODULE_RESET_25); - break; - default: - return 0; - } - - - mutex_lock(&data->update_lock); - status = as9716_32d_cpld_read_internal(client, reg); - - if (unlikely(status < 0)) { - goto exit; - } - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\r\n", !(status & mask)); - -exit: - mutex_unlock(&data->update_lock); - return status; -} - -static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - long reset; - int status=0, val, error; - u8 reg = 0, mask = 0; - - - error = kstrtol(buf, 10, &reset); - if (error) { - return error; - } - - switch (attr->index) { - case MODULE_RESET_1 ... MODULE_RESET_8: - reg = 0x14; - mask = 0x1 << (attr->index - MODULE_RESET_1); - break; - case MODULE_RESET_9 ... MODULE_RESET_16: - reg = 0x15; - mask = 0x1 << (attr->index - MODULE_RESET_9); - break; - case MODULE_RESET_17 ... MODULE_RESET_24: - reg = 0x14; - mask = 0x1 << (attr->index - MODULE_RESET_17); - break; - case MODULE_RESET_25 ... MODULE_RESET_32: - reg = 0x15; - mask = 0x1 << (attr->index - MODULE_RESET_25); - break; - default: - return 0; - } - mutex_lock(&data->update_lock); - - status = as9716_32d_cpld_read_internal(client, reg); - if (unlikely(status < 0)) { - goto exit; - } - - /* Update lp_mode status */ - if (reset) - { - val = status&(~mask); - } - else - { - val =status | (mask); - } - - status = as9716_32d_cpld_write_internal(client, reg, val); - if (unlikely(status < 0)) { - goto exit; - } - mutex_unlock(&data->update_lock); - return count; - -exit: - mutex_unlock(&data->update_lock); - return status; -} - - - -/* - * I2C init/probing/exit functions - */ -static int as9716_32d_cpld_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); - struct as9716_32d_cpld_data *data; - int ret = -ENODEV; - int status; - const struct attribute_group *group = NULL; - - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) - goto exit; - - data = kzalloc(sizeof(struct as9716_32d_cpld_data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->type = id->driver_data; - - - /* Register sysfs hooks */ - switch (data->type) { - case as9716_32d_fpga: - group = &as9716_32d_fpga_group; - break; - case as9716_32d_cpld1: - group = &as9716_32d_cpld1_group; - break; - case as9716_32d_cpld2: - group = &as9716_32d_cpld2_group; - break; - case as9716_32d_cpld_cpu: - /* Disable CPLD reset to avoid DUT will be reset. - */ - status=as9716_32d_cpld_write_internal(client, 0x3, 0x0); - if (status < 0) - { - dev_dbg(&client->dev, "cpu_cpld reg 0x65 err %d\n", status); - } - default: - break; - } - - if (group) { - ret = sysfs_create_group(&client->dev.kobj, group); - if (ret) { - goto exit_free; - } - } - - as9716_32d_cpld_add_client(client); - return 0; - -exit_free: - kfree(data); -exit: - return ret; -} - -static int as9716_32d_cpld_remove(struct i2c_client *client) -{ - struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); - const struct attribute_group *group = NULL; - - as9716_32d_cpld_remove_client(client); - - /* Remove sysfs hooks */ - switch (data->type) { - case as9716_32d_fpga: - group = &as9716_32d_fpga_group; - break; - case as9716_32d_cpld1: - group = &as9716_32d_cpld1_group; - break; - case as9716_32d_cpld2: - group = &as9716_32d_cpld2_group; - break; - default: - break; - } - - if (group) { - sysfs_remove_group(&client->dev.kobj, group); - } - - kfree(data); - - return 0; -} - -static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg) -{ - int status = 0, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, reg); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - return status; -} - -static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) -{ - int status = 0, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, reg, value); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - return status; -} - -int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int ret = -EPERM; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client->addr == cpld_addr) { - ret = as9716_32d_cpld_read_internal(cpld_node->client, reg); - break; - } - } - - mutex_unlock(&list_lock); - - return ret; -} -EXPORT_SYMBOL(as9716_32d_cpld_read); - -int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int ret = -EIO; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client->addr == cpld_addr) { - ret = as9716_32d_cpld_write_internal(cpld_node->client, reg, value); - break; - } - } - - mutex_unlock(&list_lock); - - return ret; -} -EXPORT_SYMBOL(as9716_32d_cpld_write); - -static struct i2c_driver as9716_32d_cpld_driver = { - .driver = { - .name = "as9716_32d_cpld", - .owner = THIS_MODULE, - }, - .probe = as9716_32d_cpld_probe, - .remove = as9716_32d_cpld_remove, - .id_table = as9716_32d_cpld_id, -}; - -static int __init as9716_32d_cpld_init(void) -{ - mutex_init(&list_lock); - return i2c_add_driver(&as9716_32d_cpld_driver); -} - -static void __exit as9716_32d_cpld_exit(void) -{ - i2c_del_driver(&as9716_32d_cpld_driver); -} - -MODULE_AUTHOR("Jostar Yang "); -MODULE_DESCRIPTION("Accton I2C CPLD driver"); -MODULE_LICENSE("GPL"); - -module_init(as9716_32d_cpld_init); -module_exit(as9716_32d_cpld_exit); - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c deleted file mode 100755 index 4d2433e7981e..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * A hwmon driver for the Accton as9716 32d fan - * - * Copyright (C) 2014 Accton Technology Corporation. - * Brandon Chuang - * - * This program 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "as9716_32d_fan" - -#define NUM_THERMAL_SENSORS (7) /* Get sum of this number of sensors.*/ -#define THERMAL_SENSORS_DRIVER "lm75" -#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4c , 0x4e} - -static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev); -static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, - const char *buf, size_t count); -static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); - -/* fan related data, the index should match sysfs_fan_attributes - */ -static const u8 fan_reg[] = { - 0x0F, /* fan 1-6 present status */ - 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ - 0x11, /* fan PWM(for all fan) */ - 0x12, /* front fan 1 speed(rpm) */ - 0x13, /* front fan 2 speed(rpm) */ - 0x14, /* front fan 3 speed(rpm) */ - 0x15, /* front fan 4 speed(rpm) */ - 0x16, /* front fan 5 speed(rpm) */ - 0x17, /* front fan 6 speed(rpm) */ - 0x22, /* rear fan 1 speed(rpm) */ - 0x23, /* rear fan 2 speed(rpm) */ - 0x24, /* rear fan 3 speed(rpm) */ - 0x25, /* rear fan 4 speed(rpm) */ - 0x26, /* rear fan 5 speed(rpm) */ - 0x27, /* rear fan 6 speed(rpm) */ -}; - -/* Each client has this additional data */ -struct as9716_32d_fan_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* != 0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ - int system_temp; /*In unit of mini-Celsius*/ - int sensors_found; -}; - -enum fan_id { - FAN1_ID, - FAN2_ID, - FAN3_ID, - FAN4_ID, - FAN5_ID, - FAN6_ID -}; - -enum sysfs_fan_attributes { - FAN_PRESENT_REG, - FAN_DIRECTION_REG, - FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ - FAN1_FRONT_SPEED_RPM, - FAN2_FRONT_SPEED_RPM, - FAN3_FRONT_SPEED_RPM, - FAN4_FRONT_SPEED_RPM, - FAN5_FRONT_SPEED_RPM, - FAN6_FRONT_SPEED_RPM, - FAN1_REAR_SPEED_RPM, - FAN2_REAR_SPEED_RPM, - FAN3_REAR_SPEED_RPM, - FAN4_REAR_SPEED_RPM, - FAN5_REAR_SPEED_RPM, - FAN6_REAR_SPEED_RPM, - FAN1_DIRECTION, - FAN2_DIRECTION, - FAN3_DIRECTION, - FAN4_DIRECTION, - FAN5_DIRECTION, - FAN6_DIRECTION, - FAN1_PRESENT, - FAN2_PRESENT, - FAN3_PRESENT, - FAN4_PRESENT, - FAN5_PRESENT, - FAN6_PRESENT, - FAN1_FAULT, - FAN2_FAULT, - FAN3_FAULT, - FAN4_FAULT, - FAN5_FAULT, - FAN6_FAULT -}; - -/* Define attributes - */ -#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ - static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ - static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) - -#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ - &sensor_dev_attr_fan##index2##_fault.dev_attr.attr - - -#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ - static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) -#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr - -#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ - static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) -#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr - -#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ - static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) - -#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr - -#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ - static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) -#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr - -#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ - static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ - static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ - static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ - static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) -#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ - &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ - &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ - &sensor_dev_attr_fan##index2##_input.dev_attr.attr - -/* 6 fan fault attributes in this platform */ -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); -DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); - -/* 6 fan speed(rpm) attributes in this platform */ -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); -DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); -/* 6 fan present attributes in this platform */ -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); -DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); -/* 6 fan direction attribute in this platform */ -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); -DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); -/* 1 fan duty cycle attribute in this platform */ -DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); -/* System temperature for fancontrol */ -DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); - -static struct attribute *as9716_32d_fan_attributes[] = { - /* fan related attributes */ - DECLARE_FAN_FAULT_ATTR(1,11), - DECLARE_FAN_FAULT_ATTR(2,12), - DECLARE_FAN_FAULT_ATTR(3,13), - DECLARE_FAN_FAULT_ATTR(4,14), - DECLARE_FAN_FAULT_ATTR(5,15), - DECLARE_FAN_FAULT_ATTR(6,16), - DECLARE_FAN_SPEED_RPM_ATTR(1,11), - DECLARE_FAN_SPEED_RPM_ATTR(2,12), - DECLARE_FAN_SPEED_RPM_ATTR(3,13), - DECLARE_FAN_SPEED_RPM_ATTR(4,14), - DECLARE_FAN_SPEED_RPM_ATTR(5,15), - DECLARE_FAN_SPEED_RPM_ATTR(6,16), - DECLARE_FAN_PRESENT_ATTR(1), - DECLARE_FAN_PRESENT_ATTR(2), - DECLARE_FAN_PRESENT_ATTR(3), - DECLARE_FAN_PRESENT_ATTR(4), - DECLARE_FAN_PRESENT_ATTR(5), - DECLARE_FAN_PRESENT_ATTR(6), - DECLARE_FAN_DIRECTION_ATTR(1), - DECLARE_FAN_DIRECTION_ATTR(2), - DECLARE_FAN_DIRECTION_ATTR(3), - DECLARE_FAN_DIRECTION_ATTR(4), - DECLARE_FAN_DIRECTION_ATTR(5), - DECLARE_FAN_DIRECTION_ATTR(6), - DECLARE_FAN_DUTY_CYCLE_ATTR(), - DECLARE_FAN_SYSTEM_TEMP_ATTR(), - NULL -}; - -#define FAN_DUTY_CYCLE_REG_MASK 0xF -#define FAN_MAX_DUTY_CYCLE 100 -#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 - -static int as9716_32d_fan_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int as9716_32d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* fan utility functions - */ -static u32 reg_val_to_duty_cycle(u8 reg_val) -{ - reg_val &= FAN_DUTY_CYCLE_REG_MASK; - return ((u32)(reg_val+1) * 625 + 75)/ 100; -} - -static u8 duty_cycle_to_reg_val(u8 duty_cycle) -{ - return ((u32)duty_cycle * 100 / 625) - 1; -} - -static u32 reg_val_to_speed_rpm(u8 reg_val) -{ - return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; -} - -static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) -{ - u8 mask = (1 << id); - - reg_val &= mask; - - return reg_val ? 1 : 0; -} -static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) -{ - u8 mask = (1 << id); - - reg_val &= mask; - - return reg_val ? 0 : 1; -} - -static u8 is_fan_fault(struct as9716_32d_fan_data *data, enum fan_id id) -{ - u8 ret = 1; - int front_fan_index = FAN1_FRONT_SPEED_RPM + id; - int rear_fan_index = FAN1_REAR_SPEED_RPM + id; - - /* Check if the speed of front or rear fan is ZERO, - */ - if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && - reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { - ret = 0; - } - - return ret; -} - -static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - int error, value; - struct i2c_client *client = to_i2c_client(dev); - - error = kstrtoint(buf, 10, &value); - if (error) - return error; - - if (value < 0 || value > FAN_MAX_DUTY_CYCLE) - return -EINVAL; - - as9716_32d_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ - as9716_32d_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); - return count; -} - -/* Due to this struct is declared at lm75.c, it cannot be include - * under Sonic environment. I duplicate it from lm75.c. - */ -struct lm75_data { - struct i2c_client *client; - struct device *hwmon_dev; - struct thermal_zone_device *tz; - struct mutex update_lock; - u8 orig_conf; - u8 resolution; /* In bits, between 9 and 12 */ - u8 resolution_limits; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned long sample_time; /* In jiffies */ - s16 temp[3]; /* Register values, - 0 = input - 1 = max - 2 = hyst */ -}; - -/*Copied from lm75.c*/ -static inline long lm75_reg_to_mc(s16 temp, u8 resolution) -{ - return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); -} - -/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ -static struct device * get_hwmon_dev( - struct i2c_client *client) -{ - struct lm75_data *data = NULL; - - data = i2c_get_clientdata(client); - if(data) - { - if( data->valid == 1 && data->hwmon_dev) - { - return data->hwmon_dev; - } - - } - return NULL; -} - -/* To find hwmon index by opening hwmon under that i2c address. - */ -static int find_hwmon_index_by_FileOpen( - int bus_nr, - unsigned short addr, - int *index) -{ -#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ - struct file *sfd; - char client_name[96]; - int i=0; - - do { - snprintf(client_name, sizeof(client_name), - "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", - bus_nr, addr, i); - - sfd = filp_open(client_name, O_RDONLY, 0); - i++; - } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); - - if (IS_ERR(sfd)) { - pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); - return -ENOENT; - } - filp_close(sfd, 0); - *index = i - 1; - return 0; - -#undef MAX_HWMON_DEVICE -} - -static int get_temp_file_path( - int bus_nr, unsigned short addr, - struct device *hwmon_dev - ,char *path, int max_len) -{ - - if(hwmon_dev && strlen(dev_name(hwmon_dev))) - { - snprintf(path, max_len, - "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", - bus_nr, addr, dev_name(hwmon_dev)); - } - else - { - int i=0; - if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) - { - return -EIO; - } - snprintf(path, max_len, - "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", - bus_nr, addr, i); - } - - return 0; -} - -/*File read the dev file at user space.*/ -static int read_devfile_temp1_input( - struct device *dev, - int bus_nr, - unsigned short addr, - struct device *hwmon_dev, - int *miniCelsius) -{ - struct file *sfd; - char buffer[96]; - char devfile[96]; - int rc, status; - int rdlen, value; - mm_segment_t old_fs; - - rc = 0; - get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); - sfd = filp_open(devfile, O_RDONLY, 0); - if (IS_ERR(sfd)) { - pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); - return -ENOENT; - } - dev_dbg(dev, "Found device:%s\n",devfile); - - if(!(sfd->f_op) || !(sfd->f_op->read) ) { - pr_err("file %s cann't readable ?\n",devfile); - return -ENOENT; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); - if (rdlen == 0) { - pr_err( "File(%s) empty!\n", devfile); - rc = -EIO; - goto exit; - } - status = sscanf(buffer, "%d", &value); - if (status != 1) { - rc = -EIO; - goto exit; - } - *miniCelsius = value; - dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); - -exit: - set_fs(old_fs); - filp_close(sfd, 0); - return rc; -} - -static u8 is_lm75_data_due(struct i2c_client *client) -{ - struct lm75_data *data = NULL; - - data = i2c_get_clientdata(client); - if (time_after(jiffies, data->last_updated + data->sample_time)) - { - return 1; - } - return 0; -} -static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) -{ - struct lm75_data *data = NULL; - - data = i2c_get_clientdata(client); - *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); - - return 0; -} - -static bool lm75_addr_mached(unsigned short addr) -{ - int i; - unsigned short addrs[] = THERMAL_SENSORS_ADDRS; - - for (i = 0; i < ARRAY_SIZE(addrs); i++) - { - if( addr == addrs[i]) - return 1; - } - return 0; -} - -static int _find_lm75_device(struct device *dev, void *data) -{ - struct device_driver *driver; - struct as9716_32d_fan_data *prv = data; - char *driver_name = THERMAL_SENSORS_DRIVER; - - driver = dev->driver; - if (driver && driver->name && - strcmp(driver->name, driver_name) == 0) - { - struct i2c_client *client; - client = to_i2c_client(dev); - if (client) - { - /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ - struct i2c_adapter *adap = client->adapter; - int miniCelsius = 0; - - if (! lm75_addr_mached(client->addr)) - { - return 0; - } - - if (!adap) { - return -ENXIO; - } - - /* If the data is not updated, read them from devfile - to drive them updateing data from chip.*/ - if (is_lm75_data_due(client)) - { - struct device *hwmon_dev; - - hwmon_dev = get_hwmon_dev(client); - if(0 == read_devfile_temp1_input(dev, adap->nr, - client->addr, hwmon_dev, &miniCelsius)) - { - prv->system_temp += miniCelsius; - prv->sensors_found++; - } - - } - else - { - get_lm75_temp(client, &miniCelsius); - prv->system_temp += miniCelsius; - prv->sensors_found++; - - } - } - } - return 0; -} - -/*Find all lm75 devices and return sum of temperatures.*/ -static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - ssize_t ret = 0; - struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); - - data->system_temp=0; - data->sensors_found=0; - i2c_for_each_dev(data, _find_lm75_device); - if (NUM_THERMAL_SENSORS != data->sensors_found) - { - dev_dbg(dev,"only %d of %d temps are found\n", - data->sensors_found, NUM_THERMAL_SENSORS); - data->system_temp = INT_MAX; - } - ret = sprintf(buf, "%d\n",data->system_temp); - return ret; -} - -static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); - ssize_t ret = 0; - - if (data->valid) { - switch (attr->index) { - case FAN_DUTY_CYCLE_PERCENTAGE: - { - u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); - ret = sprintf(buf, "%u\n", duty_cycle); - break; - } - case FAN1_FRONT_SPEED_RPM: - case FAN2_FRONT_SPEED_RPM: - case FAN3_FRONT_SPEED_RPM: - case FAN4_FRONT_SPEED_RPM: - case FAN5_FRONT_SPEED_RPM: - case FAN6_FRONT_SPEED_RPM: - case FAN1_REAR_SPEED_RPM: - case FAN2_REAR_SPEED_RPM: - case FAN3_REAR_SPEED_RPM: - case FAN4_REAR_SPEED_RPM: - case FAN5_REAR_SPEED_RPM: - case FAN6_REAR_SPEED_RPM: - ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); - break; - case FAN1_PRESENT: - case FAN2_PRESENT: - case FAN3_PRESENT: - case FAN4_PRESENT: - case FAN5_PRESENT: - case FAN6_PRESENT: - ret = sprintf(buf, "%d\n", - reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], - attr->index - FAN1_PRESENT)); - break; - case FAN1_FAULT: - case FAN2_FAULT: - case FAN3_FAULT: - case FAN4_FAULT: - case FAN5_FAULT: - case FAN6_FAULT: - ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); - break; - case FAN1_DIRECTION: - case FAN2_DIRECTION: - case FAN3_DIRECTION: - case FAN4_DIRECTION: - case FAN5_DIRECTION: - case FAN6_DIRECTION: - ret = sprintf(buf, "%d\n", - reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], - attr->index - FAN1_DIRECTION)); - break; - default: - break; - } - } - - return ret; -} - -static const struct attribute_group as9716_32d_fan_group = { - .attrs = as9716_32d_fan_attributes, -}; - -static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_fan_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || - !data->valid) { - int i; - - dev_dbg(&client->dev, "Starting as9716_32d_fan update\n"); - data->valid = 0; - - /* Update fan data - */ - for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { - int status = as9716_32d_fan_read_value(client, fan_reg[i]); - if (status < 0) { - data->valid = 0; - mutex_unlock(&data->update_lock); - dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); - return data; - } - else { - data->reg_val[i] = status; - } - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static int as9716_32d_fan_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct as9716_32d_fan_data *data; - int status; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - status = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct as9716_32d_fan_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - dev_info(&client->dev, "chip found\n"); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &as9716_32d_fan_group); - if (status) { - goto exit_free; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "%s: fan '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); -exit_free: - kfree(data); -exit: - - return status; -} - -static int as9716_32d_fan_remove(struct i2c_client *client) -{ - struct as9716_32d_fan_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); - - return 0; -} - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; - -static const struct i2c_device_id as9716_32d_fan_id[] = { - { "as9716_32d_fan", 0 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, as9716_32d_fan_id); - -static struct i2c_driver as9716_32d_fan_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = DRVNAME, - }, - .probe = as9716_32d_fan_probe, - .remove = as9716_32d_fan_remove, - .id_table = as9716_32d_fan_id, - .address_list = normal_i2c, -}; - -module_i2c_driver(as9716_32d_fan_driver); - -MODULE_AUTHOR("Jostar Yang "); -MODULE_DESCRIPTION("as9716_32d_fan driver"); -MODULE_LICENSE("GPL"); - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c deleted file mode 100755 index 0fd28a4631b2..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * A LED driver for the accton_as9716_32d_led - * - * Copyright (C) 2014 Accton Technology Corporation. - * Brandon Chuang - * - * This program 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*#define DEBUG*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -extern int as9716_32d_cpld_read (unsigned short cpld_addr, u8 reg); -extern int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -#define DRVNAME "accton_as9716_32d_led" - -struct accton_as9716_32d_led_data { - struct platform_device *pdev; - struct mutex update_lock; - char valid; /* != 0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 reg_val[2]; /* only 1 register*/ -}; - -static struct accton_as9716_32d_led_data *ledctl = NULL; - -/* LED related data - */ - -#define LED_CNTRLER_I2C_ADDRESS (0x61) - -#define LED_TYPE_DIAG_REG_MASK (0x1|0x2|0x4) -#define LED_MODE_DIAG_GREEN_VALUE (0x01) -#define LED_MODE_DIAG_AMBER_VALUE (0x02) /*It's yellow actually. Green+Red=Yellow*/ -#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x04) -#define LED_MODE_DIAG_OFF_VALUE (0x0) - - -#define LED_TYPE_LOC_REG_MASK (0x80|0x40) -#define LED_MODE_LOC_GREEN_BLIKN_VALUE 0x80 -#define LED_MODE_LOC_AMBER_VALUE 0x40 -#define LED_MODE_LOC_OFF_VALUE (0x0) - -#define LED_TYPE_FAN_REG_MASK (0x20|0x10) -#define LED_MODE_FAN_AMBER_VALUE 0x20 -#define LED_MODE_FAN_GREEN_VALUE 0x10 -#define LED_MODE_FAN_OFF_VALUE (0x0) - -#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) -#define LED_MODE_PSU2_AMBER_VALUE 0x8 -#define LED_MODE_PSU2_GREEN_VALUE 0x4 -#define LED_MODE_PSU2_OFF_VALUE (0x0) - -#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) -#define LED_MODE_PSU1_AMBER_VALUE 0x2 -#define LED_MODE_PSU1_GREEN_VALUE 0x1 -#define LED_MODE_PSU1_OFF_VALUE (0x0) - -enum led_type { - LED_TYPE_DIAG, - LED_TYPE_LOC, - LED_TYPE_FAN, - LED_TYPE_PSU1, - LED_TYPE_PSU2 -}; - -struct led_reg { - u32 types; - u8 reg_addr; -}; - -static const struct led_reg led_reg_map[] = { - {(1<update_lock); - - if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) - || !ledctl->valid) { - int i; - - dev_dbg(&ledctl->pdev->dev, "Starting accton_as9716_32d_led update\n"); - - /* Update LED data - */ - for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { - int status = accton_as9716_32d_led_read_value(led_reg_map[i].reg_addr); - - if (status < 0) { - ledctl->valid = 0; - dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); - goto exit; - } - else - { - ledctl->reg_val[i] = status; - } - } - - ledctl->last_updated = jiffies; - ledctl->valid = 1; - } - -exit: - mutex_unlock(&ledctl->update_lock); -} - -static void accton_as9716_32d_led_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode, - enum led_type type) -{ - int reg_val; - u8 reg ; - mutex_lock(&ledctl->update_lock); - - if( !accton_getLedReg(type, ®)) - { - dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); - } - - reg_val = accton_as9716_32d_led_read_value(reg); - - if (reg_val < 0) { - dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); - goto exit; - } - reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); - - accton_as9716_32d_led_write_value(reg, reg_val); - - /* to prevent the slow-update issue */ - ledctl->valid = 0; - -exit: - mutex_unlock(&ledctl->update_lock); -} - - -static void accton_as9716_32d_led_diag_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); -} - -static enum led_brightness accton_as9716_32d_led_diag_get(struct led_classdev *cdev) -{ - accton_as9716_32d_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); -} - -static void accton_as9716_32d_led_loc_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); -} - -static enum led_brightness accton_as9716_32d_led_loc_get(struct led_classdev *cdev) -{ - accton_as9716_32d_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[1]); -} - -static void accton_as9716_32d_led_fan_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); -} - -static enum led_brightness accton_as9716_32d_led_fan_get(struct led_classdev *cdev) -{ - accton_as9716_32d_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); -} - -static void accton_as9716_32d_led_psu1_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); -} - -static enum led_brightness accton_as9716_32d_led_psu1_get(struct led_classdev *cdev) -{ - accton_as9716_32d_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); -} - -static void accton_as9716_32d_led_psu2_set(struct led_classdev *led_cdev, - enum led_brightness led_light_mode) -{ - accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); -} - -static enum led_brightness accton_as9716_32d_led_psu2_get(struct led_classdev *cdev) -{ - accton_as9716_32d_led_update(); - return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); -} - -static struct led_classdev accton_as9716_32d_leds[] = { - [LED_TYPE_DIAG] = { - .name = "accton_as9716_32d_led::diag", - .default_trigger = "unused", - .brightness_set = accton_as9716_32d_led_diag_set, - .brightness_get = accton_as9716_32d_led_diag_get, - .flags = LED_CORE_SUSPENDRESUME, - .max_brightness = LED_MODE_GREEN_BLINK, - }, - [LED_TYPE_LOC] = { - .name = "accton_as9716_32d_led::loc", - .default_trigger = "unused", - .brightness_set = accton_as9716_32d_led_loc_set, - .brightness_get = accton_as9716_32d_led_loc_get, - .flags = LED_CORE_SUSPENDRESUME, - .max_brightness = LED_MODE_GREEN_BLINK, - }, - [LED_TYPE_FAN] = { - .name = "accton_as9716_32d_led::fan", - .default_trigger = "unused", - .brightness_set = accton_as9716_32d_led_fan_set, - .brightness_get = accton_as9716_32d_led_fan_get, - .flags = LED_CORE_SUSPENDRESUME, - .max_brightness = LED_MODE_AMBER, - }, - [LED_TYPE_PSU1] = { - .name = "accton_as9716_32d_led::psu1", - .default_trigger = "unused", - .brightness_set = accton_as9716_32d_led_psu1_set, - .brightness_get = accton_as9716_32d_led_psu1_get, - .flags = LED_CORE_SUSPENDRESUME, - .max_brightness = LED_MODE_AMBER, - }, - [LED_TYPE_PSU2] = { - .name = "accton_as9716_32d_led::psu2", - .default_trigger = "unused", - .brightness_set = accton_as9716_32d_led_psu2_set, - .brightness_get = accton_as9716_32d_led_psu2_get, - .flags = LED_CORE_SUSPENDRESUME, - .max_brightness = LED_MODE_AMBER, - }, -}; - -static int accton_as9716_32d_led_suspend(struct platform_device *dev, - pm_message_t state) -{ - int i = 0; - - for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { - led_classdev_suspend(&accton_as9716_32d_leds[i]); - } - - return 0; -} - -static int accton_as9716_32d_led_resume(struct platform_device *dev) -{ - int i = 0; - - for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { - led_classdev_resume(&accton_as9716_32d_leds[i]); - } - - return 0; -} - -static int accton_as9716_32d_led_probe(struct platform_device *pdev) -{ - int ret, i; - - for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { - ret = led_classdev_register(&pdev->dev, &accton_as9716_32d_leds[i]); - - if (ret < 0) - break; - } - - /* Check if all LEDs were successfully registered */ - if (i != ARRAY_SIZE(accton_as9716_32d_leds)) { - int j; - - /* only unregister the LEDs that were successfully registered */ - for (j = 0; j < i; j++) { - led_classdev_unregister(&accton_as9716_32d_leds[i]); - } - } - - return ret; -} - -static int accton_as9716_32d_led_remove(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { - led_classdev_unregister(&accton_as9716_32d_leds[i]); - } - - return 0; -} - -static struct platform_driver accton_as9716_32d_led_driver = { - .probe = accton_as9716_32d_led_probe, - .remove = accton_as9716_32d_led_remove, - .suspend = accton_as9716_32d_led_suspend, - .resume = accton_as9716_32d_led_resume, - .driver = { - .name = DRVNAME, - .owner = THIS_MODULE, - }, -}; - -static int __init accton_as9716_32d_led_init(void) -{ - int ret; - - ret = platform_driver_register(&accton_as9716_32d_led_driver); - if (ret < 0) { - goto exit; - } - - ledctl = kzalloc(sizeof(struct accton_as9716_32d_led_data), GFP_KERNEL); - if (!ledctl) { - ret = -ENOMEM; - platform_driver_unregister(&accton_as9716_32d_led_driver); - goto exit; - } - - mutex_init(&ledctl->update_lock); - - ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); - if (IS_ERR(ledctl->pdev)) { - ret = PTR_ERR(ledctl->pdev); - platform_driver_unregister(&accton_as9716_32d_led_driver); - kfree(ledctl); - goto exit; - } - -exit: - return ret; -} - -static void __exit accton_as9716_32d_led_exit(void) -{ - platform_device_unregister(ledctl->pdev); - platform_driver_unregister(&accton_as9716_32d_led_driver); - kfree(ledctl); -} - -module_init(accton_as9716_32d_led_init); -module_exit(accton_as9716_32d_led_exit); - -MODULE_AUTHOR("Jostar Yang "); -MODULE_DESCRIPTION("accton_as9716_32d_led driver"); -MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c deleted file mode 100755 index 06e8e23c3c53..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * An hwmon driver for accton as9716_32d Power Module - * - * Copyright (C) 2014 Accton Technology Corporation. - * Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * This program 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_MODEL_NAME 16 -#define MAX_SERIAL_NUMBER 19 - -static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); -static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg); - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; - -/* Each client has this additional data - */ -struct as9716_32d_psu_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 index; /* PSU index */ - u8 status; /* Status(present/power_good) register read from CPLD */ - char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ - char serial_number[MAX_SERIAL_NUMBER]; -}; - -static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev); - -enum as9716_32d_psu_sysfs_attributes { - PSU_PRESENT, - PSU_MODEL_NAME, - PSU_POWER_GOOD, - PSU_SERIAL_NUMBER -}; - -/* sysfs attributes for hwmon - */ -static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); -static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); -static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); -static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); - - -static struct attribute *as9716_32d_psu_attributes[] = { - &sensor_dev_attr_psu_present.dev_attr.attr, - &sensor_dev_attr_psu_model_name.dev_attr.attr, - &sensor_dev_attr_psu_power_good.dev_attr.attr, - &sensor_dev_attr_psu_serial_number.dev_attr.attr, - NULL -}; - -static ssize_t show_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); - u8 status = 0; - - if (attr->index == PSU_PRESENT) { - status = !(data->status >> (1-data->index) & 0x1); - } - else { /* PSU_POWER_GOOD */ - status = (data->status >> (3-data->index) & 0x1); - } - - return sprintf(buf, "%d\n", status); -} - -static ssize_t show_string(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); - char *ptr = NULL; - - if (!data->valid) { - return -EIO; - } - - switch (attr->index) { - case PSU_MODEL_NAME: - ptr = data->model_name; - break; - case PSU_SERIAL_NUMBER: - ptr = data->serial_number; - break; - default: - return -EINVAL; - } - - return sprintf(buf, "%s\n", ptr); -} - -static const struct attribute_group as9716_32d_psu_group = { - .attrs = as9716_32d_psu_attributes, -}; - -static int as9716_32d_psu_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct as9716_32d_psu_data *data; - int status; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { - status = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct as9716_32d_psu_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - data->index = dev_id->driver_data; - mutex_init(&data->update_lock); - - dev_info(&client->dev, "chip found\n"); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &as9716_32d_psu_group); - if (status) { - goto exit_free; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "%s: psu '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); -exit_free: - kfree(data); -exit: - - return status; -} - -static int as9716_32d_psu_remove(struct i2c_client *client) -{ - struct as9716_32d_psu_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); - kfree(data); - - return 0; -} - -enum psu_index -{ - as9716_32d_psu1, - as9716_32d_psu2 -}; - -static const struct i2c_device_id as9716_32d_psu_id[] = { - { "as9716_32d_psu1", as9716_32d_psu1 }, - { "as9716_32d_psu2", as9716_32d_psu2 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, as9716_32d_psu_id); - -static struct i2c_driver as9716_32d_psu_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "as9716_32d_psu", - }, - .probe = as9716_32d_psu_probe, - .remove = as9716_32d_psu_remove, - .id_table = as9716_32d_psu_id, - .address_list = normal_i2c, -}; - -static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ - int result = 0; - int retry_count = 5; - - while (retry_count) { - retry_count--; - - result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - - if (unlikely(result < 0)) { - msleep(10); - continue; - } - - if (unlikely(result != data_len)) { - result = -EIO; - msleep(10); - continue; - } - - result = 0; - break; - } - - return result; -} - -static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct as9716_32d_psu_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int status; - int power_good = 0; - - dev_dbg(&client->dev, "Starting as9716_32d update\n"); - - /* Read psu status */ - status = as9716_32d_cpld_read(0x60, 0x3); - - if (status < 0) { - dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); - } - else { - data->status = status; - } - - /* Read model name */ - memset(data->model_name, 0, sizeof(data->model_name)); - memset(data->serial_number, 0, sizeof(data->serial_number)); - power_good = (data->status >> (3-data->index) & 0x1); - - if (power_good) { - status = as9716_32d_psu_read_block(client, 0x20, data->model_name, - ARRAY_SIZE(data->model_name)-1); - if (status < 0) { - data->model_name[0] = '\0'; - dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); - } - else { - data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; - - } - /* Read from offset 0x2e ~ 0x3d (16 bytes) */ - status = as9716_32d_psu_read_block(client, 0x2e,data->serial_number, MAX_SERIAL_NUMBER); - if (status < 0) - { - data->serial_number[0] = '\0'; - dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); - } - data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(as9716_32d_psu_driver); - -MODULE_AUTHOR("Jostar Yang "); -MODULE_DESCRIPTION("as9716_32d_psu driver"); -MODULE_LICENSE("GPL"); - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c deleted file mode 100755 index df7324de5604..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * An hwmon driver for the Accton Redundant Power Module - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" -/* PMBus Protocol. */ -#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 -#define PMBUS_REGISTER_VOUT_MODE 0x20 -#define PMBUS_REGISTER_STATUS_BYTE 0x78 -#define PMBUS_REGISTER_STATUS_WORD 0x79 -#define PMBUS_REGISTER_STATUS_FAN 0x81 -#define PMBUS_REGISTER_READ_VIN 0x88 -#define PMBUS_REGISTER_READ_IIN 0x89 -#define PMBUS_REGISTER_READ_VOUT 0x8B -#define PMBUS_REGISTER_READ_IOUT 0x8C -#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D -#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E -#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F -#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 -#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 - -#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A -#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B - -#define PMBUS_REGISTER_READ_POUT 0x96 -#define PMBUS_REGISTER_READ_PIN 0x97 -#define PMBUS_REGISTER_MFR_ID 0x99 -#define PMBUS_REGISTER_MFR_MODEL 0x9A -#define PMBUS_REGISTER_MFR_REVISION 0x9B -#define PMBUS_REGISTER_MFR_SERIAL 0x9E - - -#define MAX_FAN_DUTY_CYCLE 100 -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -/* Each client has this additional data - */ -struct accton_i2c_psu_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 vout_mode; /* Register value */ - u16 v_in; /* Register value */ - u16 v_out; /* Register value */ - u16 i_in; /* Register value */ - u16 i_out; /* Register value */ - u16 p_in; /* Register value */ - u16 p_out; /* Register value */ - u16 temp_input[2]; /* Register value */ - u8 fan_fault; /* Register value */ - u16 fan_duty_cycle[2]; /* Register value */ - u16 fan_speed[2]; /* Register value */ - u8 pmbus_revision; /* Register value */ - u8 mfr_id[10]; /* Register value */ - u8 mfr_model[16]; /* Register value */ - u8 mfr_revsion[3]; /* Register value */ - u8 mfr_serial[26]; /* Register value */ -}; - -static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t show_ascii(struct device *dev, struct device_attribute *da, - char *buf); -static ssize_t show_byte(struct device *dev, struct device_attribute *da, - char *buf); - -static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); -static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); - -enum accton_i2c_psu_sysfs_attributes { - PSU_V_IN, - PSU_V_OUT, - PSU_I_IN, - PSU_I_OUT, - PSU_P_IN, - PSU_P_OUT_UV, - PSU_P_OUT, - PSU_TEMP1_INPUT, - PSU_FAN1_FAULT, - PSU_FAN1_DUTY_CYCLE, - PSU_FAN1_SPEED, - PSU_PMBUS_REVISION, - PSU_MFR_ID, - PSU_MFR_MODEL, - PSU_MFR_REVISION, - PSU_MFR_SERIAL, -}; - -/* sysfs attributes for hwmon - */ -static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); -static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); -static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); -static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); -static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); -static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); -static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); -static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); -static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); -static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); -static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); -static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); -static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); -static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); -static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); - - -/*Duplicate nodes for lm-sensors.*/ -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); -static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); -static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); -//static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); - - -static struct attribute *accton_i2c_psu_attributes[] = { - &sensor_dev_attr_psu_v_in.dev_attr.attr, - &sensor_dev_attr_psu_v_out.dev_attr.attr, - &sensor_dev_attr_psu_i_in.dev_attr.attr, - &sensor_dev_attr_psu_i_out.dev_attr.attr, - &sensor_dev_attr_psu_p_in.dev_attr.attr, - &sensor_dev_attr_psu_p_out.dev_attr.attr, - &sensor_dev_attr_psu_temp1_input.dev_attr.attr, - &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, - &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, - &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, - &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, - &sensor_dev_attr_psu_mfr_id.dev_attr.attr, - &sensor_dev_attr_psu_mfr_model.dev_attr.attr, - &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, - &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, - /*Duplicate nodes for lm-sensors.*/ - &sensor_dev_attr_curr2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_power2_input.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - //&sensor_dev_attr_temp1_fault.dev_attr.attr, - NULL -}; - -static int two_complement_to_int(u16 data, u8 valid_bit, int mask) -{ - u16 valid_data = data & mask; - bool is_negative = valid_data >> (valid_bit - 1); - - return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; -} - -static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct accton_i2c_psu_data *data = i2c_get_clientdata(client); - int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; - long speed; - int error; - - error = kstrtol(buf, 10, &speed); - if (error) - return error; - - if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->fan_duty_cycle[nr] = speed; - accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_linear(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); - - u16 value = 0; - int exponent, mantissa; - int multiplier = 0; - - switch (attr->index) { - case PSU_V_IN: - value = data->v_in; - break; - case PSU_I_IN: - value = data->i_in; - break; - case PSU_I_OUT: - value = data->i_out; - break; - case PSU_P_IN: - value = data->p_in; - break; - case PSU_P_OUT_UV: - multiplier=1; - case PSU_P_OUT: - value = data->p_out; - break; - case PSU_TEMP1_INPUT: - value = data->temp_input[0]; - break; - case PSU_FAN1_DUTY_CYCLE: - multiplier = 1; - value = data->fan_duty_cycle[0]; - break; - case PSU_FAN1_SPEED: - multiplier = 1; - value = data->fan_speed[0]; - break; - default: - break; - } - - exponent = two_complement_to_int(value >> 11, 5, 0x1f); - mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); - - if(!multiplier) - multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; - if(attr->index==PSU_P_OUT_UV) - multiplier = 1000000; - - return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : - sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); -} - -static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); - - u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; - - return sprintf(buf, "%d\n", data->fan_fault >> shift); -} - -static ssize_t show_vout(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); - int exponent, mantissa; - - exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); - mantissa = data->v_out; - - return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : - sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); -} - -static ssize_t show_byte(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); - - if (!data->valid) { - return 0; - } - - return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : - sprintf(buf, "0\n"); -} - -static ssize_t show_ascii(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); - u8 *ptr = NULL; - - if (!data->valid) { - return 0; - } - switch (attr->index) { - - case PSU_MFR_ID: - ptr = data->mfr_id; - break; - case PSU_MFR_MODEL: - ptr = data->mfr_model; - break; - case PSU_MFR_REVISION: - ptr = data->mfr_revsion; - break; - case PSU_MFR_SERIAL: - ptr = data->mfr_serial; - break; - default: - return 0; - } - - return sprintf(buf, "%s\n", ptr); -} - - -static const struct attribute_group accton_i2c_psu_group = { - .attrs = accton_i2c_psu_attributes, -}; - -static int accton_i2c_psu_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct accton_i2c_psu_data *data; - int status; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { - status = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - dev_info(&client->dev, "chip found\n"); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); - if (status) { - goto exit_free; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "%s: psu '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); -exit_free: - kfree(data); -exit: - - return status; -} - -static int accton_i2c_psu_remove(struct i2c_client *client) -{ - struct accton_i2c_psu_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); - kfree(data); - - return 0; -} -/* Support psu moduel - */ -static const struct i2c_device_id accton_i2c_psu_id[] = { - { "acbel_fsh082", 0 }, - { "yesm1300am", 1 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); - -static struct i2c_driver accton_i2c_psu_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "accton_i2c_psu", - }, - .probe = accton_i2c_psu_probe, - .remove = accton_i2c_psu_remove, - .id_table = accton_i2c_psu_id, - .address_list = normal_i2c, -}; - -static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_word_data(client, reg); -} - -static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) -{ - return i2c_smbus_write_word_data(client, reg, value); -} - -static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ - int status = 0, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - return status; -} - - -static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) -{ - int status = -EIO; - int length; - u8 buffer[128] = {0}, *ptr = buffer; - - status = accton_i2c_psu_read_byte(client, command); - if (status < 0) - { - dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); - status = -EIO; - goto EXIT_READ_BLOCK_DATA; - } - - status = (status & 0xFF) + 1; - if ( status > 128) - { - dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); - status = -EINVAL; - goto EXIT_READ_BLOCK_DATA; - } - - length = status; - status = accton_i2c_psu_read_block(client, command, buffer, length); - if (unlikely(status < 0)) - goto EXIT_READ_BLOCK_DATA; - if (unlikely(status != length)) { - status = -EIO; - goto EXIT_READ_BLOCK_DATA; - } - /* The first byte is the count byte of string. */ - ptr++; - status--; - - length=status>(data_length-1)?(data_length-1):status; - memcpy(data, ptr, length); - data[length-1] = 0; - -EXIT_READ_BLOCK_DATA: - - return status; -} - - -struct reg_data_byte { - u8 reg; - u8 *value; -}; - -struct reg_data_word { - u8 reg; - u16 *value; -}; - -static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct accton_i2c_psu_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i, status; - //u8 command, buf; - struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, - {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; - struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, - {PMBUS_REGISTER_READ_VOUT, &data->v_out}, - {PMBUS_REGISTER_READ_IIN, &data->i_in}, - {PMBUS_REGISTER_READ_IOUT, &data->i_out}, - {PMBUS_REGISTER_READ_POUT, &data->p_out}, - {PMBUS_REGISTER_READ_PIN, &data->p_in}, - {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, - {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, - {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, - {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, - {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, - }; - - dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); - - /* Read byte data */ - for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { - status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); - - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", - regs_byte[i].reg, status); - } - else { - *(regs_byte[i].value) = status; - } - } - - /* Read word data */ - for (i = 0; i < ARRAY_SIZE(regs_word); i++) { - status = accton_i2c_psu_read_word(client, regs_word[i].reg); - - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", - regs_word[i].reg, status); - } - else { - *(regs_word[i].value) = status; - } - - } - /* Read mfr_id */ - status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, - ARRAY_SIZE(data->mfr_id)); - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); - goto exit; - } - /* Read mfr_model */ - status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, - ARRAY_SIZE(data->mfr_model)); - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); - goto exit; - } - /* Read mfr_revsion */ - status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, - ARRAY_SIZE(data->mfr_revsion)); - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); - goto exit; - } - /* Read mfr_serial */ - status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, - ARRAY_SIZE(data->mfr_serial)); - if (status < 0) { - dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); - goto exit; - } - - data->last_updated = jiffies; - data->valid = 1; - } - -exit: - mutex_unlock(&data->update_lock); - - return data; -} - -static int __init accton_i2c_psu_init(void) -{ - return i2c_add_driver(&accton_i2c_psu_driver); -} - -static void __exit accton_i2c_psu_exit(void) -{ - i2c_del_driver(&accton_i2c_psu_driver); -} - -MODULE_AUTHOR("Jostar Yang "); -MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); -MODULE_LICENSE("GPL"); - -module_init(accton_i2c_psu_init); -module_exit(accton_i2c_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service deleted file mode 100755 index b77b40d67299..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Accton AS9716-32D Platform Monitoring FAN service -Before=pmon.service -After=as9716-32d-platform-monitor.service -DefaultDependencies=no - -[Service] -ExecStart=/usr/local/bin/accton_as9716_32d_monitor_fan.py -KillSignal=SIGKILL -SuccessExitStatus=SIGKILL - -# Resource Limitations -LimitCORE=infinity - -[Install] -WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service deleted file mode 100755 index 69bcf37e27f5..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Accton AS9716-32D Platform Monitoring PSU service -Before=pmon.service -After=as9716-32d-platform-monitor.service -DefaultDependencies=no - -[Service] -ExecStart=/usr/local/bin/accton_as9716_32d_monitor_psu.py -KillSignal=SIGKILL -SuccessExitStatus=SIGKILL - -# Resource Limitations -LimitCORE=infinity - -[Install] -WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service deleted file mode 100755 index 1d77c39120a5..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Accton AS9716-32D Platform Monitoring service -Before=pmon.service -After=sysinit.target -DefaultDependencies=no - -[Service] -ExecStartPre=/usr/local/bin/accton_as9716_32d_util.py install -ExecStart=/usr/local/bin/accton_as9716_32d_monitor.py -KillSignal=SIGKILL -SuccessExitStatus=SIGKILL -#StandardOutput=tty - -# Resource Limitations -LimitCORE=infinity - -[Install] -WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py deleted file mode 100755 index 7c70492e5d6d..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -from setuptools import setup -os.listdir - -setup( - name='as9716_32d', - version='1.0', - description='Module to initialize Accton AS9716-32D platforms', - - packages=['as9716_32d'], - package_dir={'as9716_32d': 'as9716-32d/classes'}, -) - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README deleted file mode 100755 index 44e03cab5f52..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README +++ /dev/null @@ -1,117 +0,0 @@ -Copyright (C) 2016 Accton Networks, Inc. - -This program 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, either version 3 of the License, or -(at your option) any later version. - -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. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Contents of this package: - patch - files under patch/ is for kernel and ONIE installer - for the kernel: - config-accton-as5712_54x.patch - for kernel configuration. - driver-i2c-muxes-pca954x-always-deselect.patch - for i2c_mux deselects after transaction. - driver-patches-for-accton-as5712-fan-psu-cpld.patch - for as5712's fan/psu/cpld/led/sfp drivers. - for ONIE: - onie_installer-accton-AS5712-54X.patch - for console port setting and copy util script o rootfs. - module - Contains source code of as5712 kernel driver modules. - -The late Sonic building scripts, pushed @Dec 5 2016, will automatically -create a docker container and run building process under it. -User is not necessary to handle docker environment creation. - -1. Download sonic-buildimage environment. - - Run "git clone https://github.com/Azure/sonic-buildimage". - - cd to sonic-buildimage and run "git submodule update --init --recursive". -2. Build kernel - - cd ./src/sonic-linux-kernel - - Copy patches and series from patch/kernel of this release to - sonic-linux-kernel/patch. - - Build kernel by "make". - - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb - , is generated. -3. Build installer - - Change directory back to sonic-buildimage/. - - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. - - Change setting for AS5712-54X by patching build_image.sh. - "patch -p1 < onie_installer-accton-AS5712-54X.patch" - !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the - "git status" checking at build_image.sh. - - The account and password of installed OS can be given at rules/config. - The default user and password are "admin" & "YourPaSsWoRd" respectively. - - Run "make configure PLATFORM=broadcom" - - Copy the built kernel debian package to target/debs/. - The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory - src/sonic-linux-kernel/. - - Run "make target/sonic-generic.bin" - - Get the installer, target/sonic-generic.bin, to target machine and install. - -All Linux kernel code is licensed under the GPLv1. All other code is -licensed under the GPLv3. Please see the LICENSE file for copies of -both licenses. - -The code for integacting with Accton AS5712-54X has 2 parts, -kernel drivers and operational script. -The kernel drivers of peripherals are under module/ directory. -1. These drivers are patched into kernel by - driver-patches-for-accton-as5712-fan-psu-cpld.patch - Or you can build the driver under module/ by setting environment variable, - KERNEL_SRC, to proper linux built directory and run make. - It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. -2. A operational script, accton_as5712_util.py, for device initializatian and - peripheral accessing should be installed at /usr/bin. - This script is generated by onie_installer-accton-AS5712-54X.patch. - It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. - Run "accton_as5712_util.py install" to install drivers. - -To initialize the system, run "accton_as5712_util.py install". -To clean up the drivers & devices, run "accton_as5712_util.py clean". -To dump information of sensors, run "accton_as5712_util.py show". -To dump SFP EEPROM, run "accton_as5712_util.py sff". -To set fan speed, run "accton_as5712_util.py set fan". -To enable/disable SFP emission, run "accton_as5712_util.py set sfp". -To set system LEDs' color, run "accton_as5712_util.py set led" -For more information, run "accton_as5712_util.py --help". - -==================================================================== -Besides applying accton_as5712_util.py to access peripherals, you can -access peripherals by sysfs nodes directly after the installation is run. - -System LED: - There are 5 system LEDs at the lower-left corner of front panel. - They are loc, diag, fan, ps1, and ps2. - The sysfs interface color mappings are as follows: - Brightness: - 0 => off - 1 => green - 2 => amber - 3 => red - 4 => blue - But not all colors are available for each LED. - -Fan Control: - There are 10 fans inside 5 fan modules. - All fans share 1 duty setting, ranged from 0~100. - -Thermal sensers: - 3 temperature sensors are controlled by the lm75 kernel modules. - -PSUs: - There 2 power supplies slot at the left/right side of the back. - Once if a PSU is not plugged, the status of it is shown failed. - -There are 48 SFP+ and 6 QSFP modules are equipped. -Before operating on PSU and QSFP+, please make sure it is well plugged. -Otherwise, operation is going to fail. - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py deleted file mode 100755 index f80c1223a83c..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py +++ /dev/null @@ -1,344 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2017 Accton Technology Corporation -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# mm/dd/yyyy (A.D.)# -# 12/19/2018:Jostar create for as9716_32d thermal plan -# ------------------------------------------------------------------ - -try: - import os - import sys, getopt - import subprocess - import click - import imp - import logging - import logging.config - import logging.handlers - import types - import time # this is only being used as part of the example - import traceback - from tabulate import tabulate - from as9716_32d.fanutil import FanUtil - from as9716_32d.thermalutil import ThermalUtil -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - -# Deafults -VERSION = '1.0' -FUNCTION_NAME = '/usr/local/bin/accton_as9716_32x_monitor' - -global log_file -global log_level - - -# Air Flow Front to Back : -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system -# One Fan fail : Change Fan speed to 100%(0x0E) - - -# Air Flow Back to Front : -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system -# One Fan fail: Change Fan speed to 100%(0x0E) -# sensor_LM75_CPU == sensor_LM75_4B - - -class switch(object): - def __init__(self, value): - self.value = value - self.fall = False - - def __iter__(self): - """Return the match method once, then stop""" - yield self.match - raise StopIteration - - def match(self, *args): - """Indicate whether or not to enter a case suite""" - if self.fall or not args: - return True - elif self.value in args: # changed for v1.5, see below - self.fall = True - return True - else: - return False - - -fan_policy_state=1 -fan_fail=0 -alarm_state = 0 #0->default or clear, 1-->alarm detect -test_temp = 0 -test_temp_list = [0, 0, 0, 0, 0, 0] -temp_test_data=0 -# Make a class we can use to capture stdout and sterr in the log -class device_monitor(object): - # static temp var - temp = 0 - new_pwm = 0 - pwm=0 - ori_pwm = 0 - default_pwm=0x4 - - def __init__(self, log_file, log_level): - """Needs a logger and a logger level.""" - # set up logging to file - logging.basicConfig( - filename=log_file, - filemode='w', - level=log_level, - format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) - # set up logging to console - if log_level == logging.DEBUG: - console = logging.StreamHandler() - console.setLevel(log_level) - formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') - console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - - sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') - sys_handler.setLevel(logging.WARNING) - logging.getLogger('').addHandler(sys_handler) - - #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) - - def get_state_from_fan_policy(self, temp, policy): - state=0 - - logging.debug('temp=%d', temp) - for i in range(0, len(policy)): - #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2]) - if temp > policy[i][2]: - if temp <= policy[i][3]: - state =i - logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) - logging.debug ('fan_state=%d', state) - break - - return state - - - def manage_fans(self): - - global fan_policy_state - global fan_fail - global test_temp - global test_temp_list - global alarm_state - global temp_test_data - - LEVEL_FAN_DEF=0 - LEVEL_FAN_MID=1 - LEVEL_FAN_MAX=2 - LEVEL_TEMP_HIGH=3 - LEVEL_TEMP_CRITICAL=4 - - - fan_policy_f2b = { - LEVEL_FAN_DEF: [38, 0x4, 0, 38000], - LEVEL_FAN_MID: [63, 0x6, 38000, 46000], - LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], - LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], - LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], - } - fan_policy_b2f = { - LEVEL_FAN_DEF: [38, 0x4, 0, 34000], - LEVEL_FAN_MID: [63, 0x8, 34000, 44000], - LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], - LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], - LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], - } - - fan_policy = fan_policy_f2b - - thermal = ThermalUtil() - fan = FanUtil() - fan_dir=fan.get_fan_dir(1) - if fan_dir == 1: - fan_dri=1 #something wrong, set fan_dir to default val - else: - fan_policy = fan_policy_b2f - - ori_pwm=fan.get_fan_duty_cycle() - new_pwm=0 - logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) - logging.debug('test_temp=%d', test_temp) - if test_temp==0: - temp1 = thermal._get_thermal_val(1) - temp2 = thermal._get_thermal_val(2) - temp3 = thermal._get_thermal_val(3) - temp4 = thermal._get_thermal_val(4) - temp5 = thermal._get_thermal_val(5) - else: - temp1 = test_temp_list[0] - temp2 = test_temp_list[1] - temp3 = test_temp_list[2] - temp4 = test_temp_list[3] - temp5 = test_temp_list[4] - fan_fail=0 - - if temp3==0: - temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% - logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') - elif temp4==0: - temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% - logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') - else: - temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 - ori_state=fan_policy_state - - #temp_test_data=temp_test_data+1000 - #temp_get = temp_get + temp_test_data - #print "Unit test:temp_get=%d"%temp_get - - fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) - #print "temp3=%d"%temp3 - #print "temp4=%d"%temp4 - #print "temp_get=%d"%temp_get - - logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5) - logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) - new_pwm = fan_policy[fan_policy_state][0] - if fan_fail==0: - logging.debug('new_fan_cycle=%d', new_pwm) - - if fan_fail==0: - if new_pwm!=ori_pwm: - fan.set_fan_duty_cycle(new_pwm) - logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) - - #Check Fan status - for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): - if fan.get_fan_status(i)==0: - new_pwm=100 - logging.debug('fan_%d fail, set pwm to 100',i) - if test_temp==0: - fan_fail=1 - fan.set_fan_duty_cycle(new_pwm) - break - else: - fan_fail=0 - - #if fan_policy_state == ori_state: - # return True - #else: - new_state = fan_policy_state - - #logging.warning('Temperature high alarm testing') - if ori_state==LEVEL_FAN_DEF: - if new_state==LEVEL_TEMP_HIGH: - if alarm_state==0: - logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected, reboot DUT') - time.sleep(2) - os.system('reboot') - if ori_state==LEVEL_FAN_MID: - if new_state==LEVEL_TEMP_HIGH: - if alarm_state==0: - logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') - if ori_state==LEVEL_FAN_MAX: - if new_state==LEVEL_TEMP_HIGH: - if alarm_state==0: - logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') - if alarm_state==1: - if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm - logging.warning('Alarm for temperature high is cleared') - alarm_state=0 - if ori_state==LEVEL_TEMP_HIGH: - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') - if new_state <= LEVEL_FAN_MID: - logging.warning('Alarm for temperature high is cleared') - alarm_state=0 - if new_state <= LEVEL_FAN_MAX: - if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm - logging.warning('Alarm for temperature high is cleared') - alarm_state=0 - if ori_state==LEVEL_TEMP_CRITICAL: - if new_state <= LEVEL_FAN_MAX: - logging.warning('Alarm for temperature critical is cleared') - - return True - -def main(argv): - log_file = '%s.log' % FUNCTION_NAME - log_level = logging.INFO - global test_temp - if len(sys.argv) != 1: - try: - opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) - except getopt.GetoptError: - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - for opt, arg in opts: - if opt == '-h': - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - elif opt in ('-d', '--debug'): - log_level = logging.DEBUG - elif opt in ('-l', '--lfile'): - log_file = arg - - if sys.argv[1]== '-t': - if len(sys.argv)!=7: - print "temp test, need input six temp" - return 0 - - i=0 - for x in range(2, 7): - test_temp_list[i]= int(sys.argv[x])*1000 - i=i+1 - test_temp = 1 - log_level = logging.DEBUG - print test_temp_list - - fan = FanUtil() - fan.set_fan_duty_cycle(38) - print "set default fan speed to 37.5%" - monitor = device_monitor(log_file, log_level) - # Loop forever, doing something useful hopefully: - while True: - #monitor.manage_fans() - time.sleep(5) - -if __name__ == '__main__': - main(sys.argv[1:]) - diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py deleted file mode 100755 index 320655361b83..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2018 Accton Technology Corporation -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# mm/dd/yyyy (A.D.) -# 12/13/2018: Jostar create for as9716-32d -# ------------------------------------------------------------------ - -try: - import os - import sys, getopt - import subprocess - import click - import imp - import logging - import logging.config - import logging.handlers - import types - import time # this is only being used as part of the example - import traceback - from tabulate import tabulate - -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - -# Deafults -VERSION = '1.0' -FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_fan' - -global log_file -global log_level - - -class switch(object): - def __init__(self, value): - self.value = value - self.fall = False - - def __iter__(self): - """Return the match method once, then stop""" - yield self.match - raise StopIteration - - def match(self, *args): - """Indicate whether or not to enter a case suite""" - if self.fall or not args: - return True - elif self.value in args: # changed for v1.5, see below - self.fall = True - return True - else: - return False - - -fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 -fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 -# Make a class we can use to capture stdout and sterr in the log -class device_monitor(object): - - def __init__(self, log_file, log_level): - - self.fan_num = 6 - self.fan_path = "/sys/bus/i2c/devices/17-0066/" - self.present = { - 0: "fan1_present", - 1: "fan2_present", - 2: "fan3_present", - 3: "fan4_present", - 4: "fan5_present", - 5: "fan6_present", - } - - self.fault = { - 0: "fan1_fault", - 1: "fan2_fault", - 2: "fan3_fault", - 3: "fan4_fault", - 4: "fan5_fault", - 5: "fan6_fault", - } - - - """Needs a logger and a logger level.""" - # set up logging to file - logging.basicConfig( - filename=log_file, - filemode='w', - level=log_level, - format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) - - # set up logging to console - if log_level == logging.DEBUG: - console = logging.StreamHandler() - console.setLevel(logging.DEBUG) - formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') - console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - - sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') - #sys_handler.setLevel(logging.WARNING) - sys_handler.setLevel(logging.INFO) - logging.getLogger('').addHandler(sys_handler) - - - #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) - - def manage_fan(self): - - FAN_STATE_REMOVE = 0 - FAN_STATE_INSERT = 1 - - FAN_STATUS_FAULT = 1 - FAN_STATUS_NORMAL = 0 - - global fan_state - global fan_status_state - - for idx in range (0, self.fan_num): - node = self.fan_path + self.present[idx] - try: - val_file = open(node) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - content = val_file.readline().rstrip() - val_file.close() - # content is a string, either "0" or "1" - if content == "1": - if fan_state[idx]!=1: - fan_state[idx]=FAN_STATE_INSERT - logging.info("FAN-%d present is detected", idx+1); - else: - if fan_state[idx]!=0: - fan_state[idx]=FAN_STATE_REMOVE - logging.warning("Alarm for FAN-%d absent is detected", idx+1) - - for idx in range (0, self.fan_num): - node = self.fan_path + self.fault[idx] - try: - val_file = open(node) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - content = val_file.readline().rstrip() - val_file.close() - # content is a string, either "0" or "1" - if content == "1": - if fan_status_state[idx]!=FAN_STATUS_FAULT: - if fan_state[idx] == FAN_STATE_INSERT: - logging.warning("Alarm for FAN-%d failed is detected", idx+1); - fan_status_state[idx]=FAN_STATUS_FAULT - else: - fan_status_state[idx]=FAN_STATUS_NORMAL - - return True - -def main(argv): - log_file = '%s.log' % FUNCTION_NAME - log_level = logging.INFO - if len(sys.argv) != 1: - try: - opts, args = getopt.getopt(argv,'hdl:',['lfile=']) - except getopt.GetoptError: - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - for opt, arg in opts: - if opt == '-h': - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - elif opt in ('-d', '--debug'): - log_level = logging.DEBUG - elif opt in ('-l', '--lfile'): - log_file = arg - monitor = device_monitor(log_file, log_level) - while True: - monitor.manage_fan() - time.sleep(3) - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py deleted file mode 100755 index a8df99430c81..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2018 Accton Technology Corporation -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# mm/dd/yyyy (A.D.) -# 12/12/2018: Jostar create for as9716-32d -# ------------------------------------------------------------------ - -try: - import os - import sys, getopt - import subprocess - import click - import imp - import logging - import logging.config - import logging.handlers - import types - import time # this is only being used as part of the example - import traceback - from tabulate import tabulate -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - -# Deafults -VERSION = '1.0' -FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_psu' - -global log_file -global log_level - - -psu_state=[2, 2] -psu_status_state=[2, 2] -# Make a class we can use to capture stdout and sterr in the log -class device_monitor(object): - - def __init__(self, log_file, log_level): - - self.psu_num = 2 - self.psu_path = "/sys/bus/i2c/devices/" - self.presence = "/psu_present" - self.oper_status = "/psu_power_good" - self.mapping = { - 0: "9-0050", - 1: "10-0051", - } - - """Needs a logger and a logger level.""" - # set up logging to file - logging.basicConfig( - filename=log_file, - filemode='w', - level=log_level, - format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) - # set up logging to console - - if log_level == logging.DEBUG: - console = logging.StreamHandler() - console.setLevel(log_level) - formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') - console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - - sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') - #sys_handler.setLevel(logging.WARNING) - sys_handler.setLevel(logging.INFO) - logging.getLogger('').addHandler(sys_handler) - - #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) - - def manage_psu(self): - - PSU_STATE_REMOVE = 0 - PSU_STATE_INSERT = 1 - - PSU_STATUS_NO_POWER = 0 - PSU_STATUS_POWER_GOOD = 1 - PSU_STATUS_IDLE =2 - - global psu_state - - for idx in range (0, self.psu_num): - node = self.psu_path + self.mapping[idx] + self.presence - try: - val_file = open(node) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - content = val_file.readline().rstrip() - val_file.close() - # content is a string, either "0" or "1" - if content == "1": - if psu_state[idx]!=1: - psu_state[idx]=PSU_STATE_INSERT - logging.info("PSU-%d present is detected", idx+1); - #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. - else: - if psu_state[idx]!=0: - psu_state[idx]=PSU_STATE_REMOVE - logging.warning("Alarm for PSU-%d absent is detected", idx+1); - psu_status_state[idx]=PSU_STATUS_IDLE - - for idx in range (0, self.psu_num): - node = self.psu_path + self.mapping[idx] + self.oper_status - try: - val_file = open(node) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - content = val_file.readline().rstrip() - val_file.close() - # content is a string, either "0" or "1" - if content == "0": - if psu_status_state[idx]!=PSU_STATUS_NO_POWER: - if psu_state[idx]==PSU_STATE_INSERT: - logging.warning("Alarm for PSU-%d failed is detected", idx+1); - psu_status_state[idx]=PSU_STATUS_NO_POWER - else: - if psu_state[idx]==PSU_STATE_INSERT: - if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: - logging.info("PSU-%d power_good is detected", idx+1); - psu_status_state[idx]=PSU_STATUS_POWER_GOOD - - - return True - -def main(argv): - log_file = '%s.log' % FUNCTION_NAME - log_level = logging.INFO - if len(sys.argv) != 1: - try: - opts, args = getopt.getopt(argv,'hdl:',['lfile=']) - except getopt.GetoptError: - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - for opt, arg in opts: - if opt == '-h': - print 'Usage: %s [-d] [-l ]' % sys.argv[0] - return 0 - elif opt in ('-d', '--debug'): - log_level = logging.DEBUG - elif opt in ('-l', '--lfile'): - log_file = arg - monitor = device_monitor(log_file, log_level) - # Loop forever, doing something useful hopefully: - while True: - monitor.manage_psu() - time.sleep(3) - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py deleted file mode 100755 index e9779db01d2a..000000000000 --- a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py +++ /dev/null @@ -1,571 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2016 Accton Networks, Inc. -# -# This program 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, either version 3 of the License, or -# (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -""" -Usage: %(scriptName)s [options] command object - -options: - -h | --help : this help message - -d | --debug : run with debug mode - -f | --force : ignore error during installation or clean -command: - install : install drivers and generate related sysfs nodes - clean : uninstall drivers and remove related sysfs nodes - show : show all systen status - sff : dump SFP eeprom - set : change board setting with fan|led|sfp -""" - -import os -import commands -import sys, getopt -import logging -import re -import time -from collections import namedtuple - -PROJECT_NAME = 'as9716_32d' -version = '0.0.1' -verbose = False -DEBUG = False -args = [] -ALL_DEVICE = {} -DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':34} - - -led_prefix ='/sys/devices/platform/as9716_32d_led/leds/accton_'+PROJECT_NAME+'_led::' -fan_prefix ='/sys/devices/platform/as9716_32d_' -hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], - 'fan1': ['fan'], - 'fan2': ['fan'], - 'fan3': ['fan'], - 'fan4': ['fan'], - 'fan5': ['fan'], - 'fan5': ['fan'], - } -hwmon_nodes = {'led': ['brightness'] , - 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], - 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], - 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], - 'fan4': ['fan_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], - 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], - 'fan6': ['fan_duty_cycle_percentage','fan6_fault', 'fan6_speed_rpm', 'fan6_direction', 'fanr5_fault', 'fanr5_speed_rpm'], - } -hwmon_prefix ={'led': led_prefix, - 'fan1': fan_prefix, - 'fan2': fan_prefix, - 'fan3': fan_prefix, - 'fan4': fan_prefix, - 'fan5': fan_prefix, - } - -i2c_prefix = '/sys/bus/i2c/devices/' -i2c_bus = {'fan': ['54-0066'], - 'thermal': ['18-0048', '18-0049','18-004a', '18-004b', '18-004c', '18-004e', '18-004f'] , - 'psu': ['9-0058', '10-0059'], - 'sfp': ['-0050']} -i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], - 'thermal': ['hwmon/hwmon*/temp1_input'] , - 'psu': ['psu_present ', 'psu_power_good'] , - 'sfp': ['module_present_ ', 'module_tx_disable_']} - -sfp_map = [25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58] - -#sfp_map = [25, 26] - -mknod =[ -'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', -'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', -'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', -'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', -'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', -'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', -'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', -'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', - -'echo as9716_32d_fpga 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', -'echo as9716_32d_cpld1 0x61 > /sys/bus/i2c/devices/i2c-20/new_device', -'echo as9716_32d_cpld2 0x62 > /sys/bus/i2c/devices/i2c-21/new_device', -'echo as9716_32d_cpld_cpu 0x65 > /sys/bus/i2c/devices/i2c-0/new_device', - -'echo as9716_32d_fan 0x66 > /sys/bus/i2c/devices/i2c-17/new_device', - -'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-18/new_device', -'echo lm75 0x4f > /sys/bus/i2c/devices/i2c-18/new_device', - -# PSU-1 -'echo as9716_32d_psu1 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', -'echo acbel_fsh082 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', - -# PSU-2 -'echo as9716_32d_psu2 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', -'echo acbel_fsh082 0x59 > /sys/bus/i2c/devices/i2c-10/new_device', - -#EERPOM -'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', -] - - - -FORCE = 0 -logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) -logging.basicConfig(level=logging.INFO) - - -if DEBUG == True: - print sys.argv[0] - print 'ARGV :', sys.argv[1:] - - -def main(): - global DEBUG - global args - global FORCE - - if len(sys.argv)<2: - show_help() - - options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', - 'debug', - 'force', - ]) - if DEBUG == True: - print options - print args - print len(sys.argv) - - for opt, arg in options: - if opt in ('-h', '--help'): - show_help() - elif opt in ('-d', '--debug'): - DEBUG = True - logging.basicConfig(level=logging.INFO) - elif opt in ('-f', '--force'): - FORCE = 1 - else: - logging.info('no option') - for arg in args: - if arg == 'install': - do_install() - elif arg == 'clean': - do_uninstall() - elif arg == 'show': - device_traversal() - elif arg == 'sff': - if len(args)!=2: - show_eeprom_help() - elif int(args[1]) > DEVICE_NO['sfp'] -1: - show_eeprom_help() - else: - show_eeprom(args[1]) - return - elif arg == 'set': - if len(args)<3: - show_set_help() - else: - set_device(args[1:]) - return - else: - show_help() - - - return 0 - -def show_help(): - print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} - sys.exit(0) - -def show_set_help(): - cmd = sys.argv[0].split("/")[-1]+ " " + args[0] - print cmd +" [led|sfp|fan]" - print " use \""+ cmd + " led 0-4 \" to set led color" - print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" - print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" - sys.exit(0) - -def show_eeprom_help(): - cmd = sys.argv[0].split("/")[-1]+ " " + args[0] - print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" - sys.exit(0) - -def my_log(txt): - if DEBUG == True: - print "[ACCTON DBG]: "+txt - return - -def log_os_system(cmd, show): - logging.info('Run :'+cmd) - status = 1 - output = "" - status, output = commands.getstatusoutput(cmd) - my_log (cmd +"with result:" + str(status)) - my_log ("cmd:" + cmd) - my_log (" output:"+output) - if status: - logging.info('Failed :'+cmd) - if show: - print('Failed :'+cmd) - return status, output - -def driver_inserted(): - ret, lsmod = log_os_system("lsmod| grep accton", 0) - logging.info('mods:'+lsmod) - if len(lsmod) ==0: - return False - - -kos = [ -'depmod -ae', -'modprobe i2c_dev', -'modprobe i2c_mux_pca954x force_deselect_on_exit=1', -'modprobe accton_i2c_psu', -'modprobe accton_as9716_32d_cpld', -'modprobe accton_as9716_32d_fan', -'modprobe accton_as9716_32d_leds', -'modprobe accton_as9716_32d_psu', -'modprobe optoe', -'modprobe lm75'] - -cpld_reset_stop='i2cset -y 0 0x65 0x3 0x0' - -def driver_install(): - - global FORCE - for i in range(0,len(kos)): - status, output = log_os_system(kos[i], 1) - if status: - if FORCE == 0: - return status - log_os_system(cpld_reset_stop, 1) - return 0 - -def driver_uninstall(): - global FORCE - for i in range(0,len(kos)): - rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") - lst = rm.split(" ") - print "lst=%s"%lst - if len(lst) > 3: - del(lst[3]) - rm = " ".join(lst) - status, output = log_os_system(rm, 1) - if status: - if FORCE == 0: - return status - return 0 - -def device_install(): - global FORCE - - for i in range(0,len(mknod)): - #for pca954x need times to built new i2c buses - if mknod[i].find('pca954') != -1: - time.sleep(2) - print "init i2c device instance" - status, output = log_os_system(mknod[i], 1) - if status: - print output - if FORCE == 0: - return status - - for i in range(0,len(sfp_map)): - status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) - if status: - print output - if FORCE == 0: - return status - status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) - if status: - print output - if FORCE == 0: - return status - return - -def device_uninstall(): - global FORCE - - status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) - if status==0: - I2C_ORDER=1 - else: - I2C_ORDER=0 - - for i in range(0,len(sfp_map)): - target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" - status, output =log_os_system("echo 0x50 > "+ target, 1) - if status: - print output - if FORCE == 0: - return status - - nodelist = mknod - - for i in range(len(nodelist)): - target = nodelist[-(i+1)] - temp = target.split() - del temp[1] - temp[-1] = temp[-1].replace('new_device', 'delete_device') - status, output = log_os_system(" ".join(temp), 1) - if status: - print output - if FORCE == 0: - return status - - return - -def system_ready(): - if driver_inserted() == False: - return False - if not device_exist(): - print "not device_exist()" - return False - return True - -def do_install(): - if driver_inserted() == False: - status = driver_install() - if status: - if FORCE == 0: - return status - else: - print PROJECT_NAME.upper()+" drivers detected...." - if not device_exist(): - status = device_install() - if status: - if FORCE == 0: - return status - else: - print PROJECT_NAME.upper()+" devices detected...." - return - -def do_uninstall(): - if not device_exist(): - print PROJECT_NAME.upper() +" has no device installed...." - else: - print "Removing device...." - status = device_uninstall() - if status: - if FORCE == 0: - return status - - if driver_inserted()== False : - print PROJECT_NAME.upper() +" has no driver installed...." - else: - print "Removing installed driver...." - status = driver_uninstall() - if status: - if FORCE == 0: - return status - - return - -def devices_info(): - global DEVICE_NO - global ALL_DEVICE - global i2c_bus, hwmon_types - for key in DEVICE_NO: - ALL_DEVICE[key]= {} - for i in range(0,DEVICE_NO[key]): - ALL_DEVICE[key][key+str(i+1)] = [] - - for key in i2c_bus: - buses = i2c_bus[key] - nodes = i2c_nodes[key] - for i in range(0,len(buses)): - for j in range(0,len(nodes)): - if 'fan' == key: - for k in range(0,DEVICE_NO[key]): - node = key+str(k+1) - path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] - my_log(node+": "+ path) - ALL_DEVICE[key][node].append(path) - elif 'sfp' == key: - for k in range(0,DEVICE_NO[key]): - node = key+str(k+1) - path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] - my_log(node+": "+ path) - ALL_DEVICE[key][node].append(path) - else: - node = key+str(i+1) - path = i2c_prefix+ buses[i]+"/"+ nodes[j] - my_log(node+": "+ path) - ALL_DEVICE[key][node].append(path) - - for key in hwmon_types: - itypes = hwmon_types[key] - nodes = hwmon_nodes[key] - for i in range(0,len(itypes)): - for j in range(0,len(nodes)): - node = key+"_"+itypes[i] - path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] - my_log(node+": "+ path) - ALL_DEVICE[key][ key+str(i+1)].append(path) - - #show dict all in the order - if DEBUG == True: - for i in sorted(ALL_DEVICE.keys()): - print(i+": ") - for j in sorted(ALL_DEVICE[i].keys()): - print(" "+j) - for k in (ALL_DEVICE[i][j]): - print(" "+" "+k) - return - -def show_eeprom(index): - if system_ready()==False: - print("System's not ready.") - print("Please install first!") - return - - #if len(ALL_DEVICE)==0: - # devices_info() - #node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] - #node = node.replace(node.split("/")[-1], 'eeprom') - node= "/sys/bus/i2c/devices/"+str(sfp_map[int(index)])+"-0050" + "/eeprom" - # check if got hexdump command in current environment - ret, log = log_os_system("which hexdump", 0) - ret, log2 = log_os_system("which busybox hexdump", 0) - if len(log): - hex_cmd = 'hexdump' - elif len(log2): - hex_cmd = ' busybox hexdump' - else: - log = 'Failed : no hexdump cmd!!' - logging.info(log) - print log - return 1 - print "node=%s"%node - #print node + ":" - #ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) - ret, log = log_os_system(hex_cmd+" -C " + node, 1) - if ret==0: - print log - else: - print "**********device no found**********" - return - -def set_device(args): - global DEVICE_NO - global ALL_DEVICE - if system_ready()==False: - print("System's not ready.") - print("Please install first!") - return - - if len(ALL_DEVICE)==0: - devices_info() - - if args[0]=='led': - if int(args[1])>4: - show_set_help() - return - #print ALL_DEVICE['led'] - for i in range(0,len(ALL_DEVICE['led'])): - for k in (ALL_DEVICE['led']['led'+str(i+1)]): - ret, log = log_os_system("echo "+args[1]+" >"+k, 1) - if ret: - return ret - elif args[0]=='fan': - if int(args[1])>100: - show_set_help() - return - #print ALL_DEVICE['fan'] - #fan1~6 is all fine, all fan share same setting - node = ALL_DEVICE['fan1'] ['fan11'][0] - node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') - ret, log = log_os_system("cat "+ node, 1) - if ret==0: - print ("Previous fan duty: " + log.strip() +"%") - ret, log = log_os_system("echo "+args[1]+" >"+node, 1) - if ret==0: - print ("Current fan duty: " + args[1] +"%") - return ret - elif args[0]=='sfp': - if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: - show_set_help() - return - if len(args)<2: - show_set_help() - return - - if int(args[2])>1: - show_set_help() - return - - #print ALL_DEVICE[args[0]] - for i in range(0,len(ALL_DEVICE[args[0]])): - for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: - if j.find('tx_disable')!= -1: - ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) - if ret: - return ret - - return - -#get digits inside a string. -#Ex: 31 for "sfp31" -def get_value(input): - digit = re.findall('\d+', input) - return int(digit[0]) - -def device_traversal(): - if system_ready()==False: - print("System's not ready.") - print("Please install first!") - return - - if len(ALL_DEVICE)==0: - devices_info() - for i in sorted(ALL_DEVICE.keys()): - print("============================================") - print(i.upper()+": ") - print("============================================") - - for j in sorted(ALL_DEVICE[i].keys(), key=get_value): - print " "+j+":", - for k in (ALL_DEVICE[i][j]): - ret, log = log_os_system("cat "+k, 0) - func = k.split("/")[-1].strip() - func = re.sub(j+'_','',func,1) - func = re.sub(i.lower()+'_','',func,1) - if ret==0: - print func+"="+log+" ", - else: - print func+"="+"X"+" ", - print - print("----------------------------------------------------------------") - - - print - return - -def device_exist(): - ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) - ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) - return not(ret1 or ret2) - -if __name__ == "__main__": - main() From 78f4fc35c24f96667bb5336c8e45cf24d47b644e Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 12 Jun 2019 17:59:16 +0800 Subject: [PATCH 3/7] remove as9716 needed mk --- platform/broadcom/one-image.mk | 1 - platform/broadcom/platform-modules-accton.mk | 5 ----- .../broadcom/sonic-platform-modules-accton/debian/control | 6 +----- .../broadcom/sonic-platform-modules-accton/debian/rules | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index d17dcfe067d7..db9acc0cc30a 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -26,7 +26,6 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_MINIPACK_PLATFORM_MODULE) \ $(ACCTON_AS5812_54X_PLATFORM_MODULE) \ $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ - $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index ebf76bbd716d..7b6ae093b8d1 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -13,7 +13,6 @@ ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1 ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 -ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -28,7 +27,6 @@ export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION -export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton @@ -85,8 +83,5 @@ ACCTON_AS5835_54X_PLATFORM_MODULE = sonic-platform-accton-as5835-54x_$(ACCTON_AS $(ACCTON_AS5835_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54x-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54X_PLATFORM_MODULE))) -ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION)_amd64.deb -$(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0 -$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE))) SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index b22828af67c5..1a36758a0fb9 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -1,7 +1,7 @@ Source: sonic-accton-platform-modules Section: main Priority: extra -Maintainer: Accton network , Accton Network , Accton Network +Maintainer: Accton network , Accton Network Build-Depends: debhelper (>= 9), bzip2 Standards-Version: 3.9.3 @@ -57,7 +57,3 @@ Package: sonic-platform-accton-as5835-54x Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp -Package: sonic-platform-accton-as9716-32d -Architecture: amd64 -Description: kernel modules for platform devices such as fan, led, sfp - diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index 46014874d5c0..60cec5ab13e5 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d +MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service From 94006a51a15adf4a37bcade6c1c01d02dabc117b Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 17 Jul 2019 11:01:24 +0800 Subject: [PATCH 4/7] Add to support as9716 platform --- .../as9716-32d/classes/__init__.py | 0 .../as9716-32d/classes/fanutil.py | 251 +++++ .../as9716-32d/classes/thermalutil.py | 135 +++ .../as9716-32d/modules/Makefile | 19 + .../modules/accton_as9716_32d_cpld.c | 900 ++++++++++++++++++ .../modules/accton_as9716_32d_fan.c | 760 +++++++++++++++ .../modules/accton_as9716_32d_leds.c | 492 ++++++++++ .../modules/accton_as9716_32d_psu.c | 311 ++++++ .../as9716-32d/modules/accton_i2c_psu.c | 602 ++++++++++++ .../as9716-32d-platform-monitor-fan.service | 16 + .../as9716-32d-platform-monitor-psu.service | 16 + .../as9716-32d-platform-monitor.service | 18 + .../as9716-32d/setup.py | 16 + .../as9716-32d/utils/README | 117 +++ .../utils/accton_as9716_32d_monitor.py | 344 +++++++ .../utils/accton_as9716_32d_monitor_fan.py | 197 ++++ .../utils/accton_as9716_32d_monitor_psu.py | 169 ++++ .../utils/accton_as9716_32d_util.py | 571 +++++++++++ .../debian/control | 6 +- .../debian/rules | 2 +- 20 files changed, 4940 insertions(+), 2 deletions(-) create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py new file mode 100755 index 000000000000..ca0f3f9da1e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 12/03/2018: Jostar modify for as7726_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py new file mode 100755 index 000000000000..00c9950d52b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/18/2018:Jostar craete for as9716_32d +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 8 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 + THERMAL_NUM_6_IDX = 6 # 6_ON_MAIN_BROAD. LM75 + THERMAL_NUM_7_IDX = 7 # 7_ON_MAIN_BROAD. LM75 + THERMAL_NUM_8_IDX = 8 # 8_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['18', '48'], + THERMAL_NUM_2_IDX: ['18', '49'], + THERMAL_NUM_3_IDX: ['18', '4a'], + THERMAL_NUM_4_IDX: ['18', '4b'], + THERMAL_NUM_5_IDX: ['18', '4c'], + THERMAL_NUM_6_IDX: ['18', '4e'], + THERMAL_NUM_7_IDX: ['18', '4f'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/18-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_7_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_8_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], + } + + #def __init__(self): + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) + print "termal5=%d" %thermal._get_thermal_val(5) + print "termal7=%d" %thermal._get_thermal_val(6) + print "termal8=%d" %thermal._get_thermal_val(7) + print "termal9=%d" %thermal._get_thermal_val(8) + +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile new file mode 100755 index 000000000000..be04fc82cb59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as9716_32d_cpld.o accton_as9716_32d_fan.o \ + accton_as9716_32d_leds.o accton_as9716_32d_psu.o accton_i2c_psu.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-8-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd *.mod.c .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c new file mode 100755 index 000000000000..874bdc33bea4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c @@ -0,0 +1,900 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as9716_32d CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as9716_32d_fpga, + as9716_32d_cpld1, + as9716_32d_cpld2, + as9716_32d_cpld_cpu +}; + +struct as9716_32d_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as9716_32d_cpld_id[] = { + { "as9716_32d_fpga", as9716_32d_fpga }, + { "as9716_32d_cpld1", as9716_32d_cpld1 }, + { "as9716_32d_cpld2", as9716_32d_cpld2 }, + { "as9716_32d_cpld_cpu", as9716_32d_cpld_cpu }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as9716_32d_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + + +static struct attribute *as9716_32d_fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9716_32d_fpga_group = { + .attrs = as9716_32d_fpga_attributes, +}; + +static struct attribute *as9716_32d_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + NULL +}; + +static const struct attribute_group as9716_32d_cpld1_group = { + .attrs = as9716_32d_cpld1_attributes, +}; + +static struct attribute *as9716_32d_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as9716_32d_cpld2_group = { + .attrs = as9716_32d_cpld2_attributes, +}; + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x20; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x20; + mask = 0x8; + break; + case MODULE_RXLOS_33: + reg = 0x20; + mask = 0x2; + break; + case MODULE_RXLOS_34: + reg = 0x20; + mask = 0x10; + break; + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as9716_32d_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as9716_32d_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as9716_32d_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as9716_32d_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +/* + * I2C init/probing/exit functions + */ +static int as9716_32d_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as9716_32d_cpld_data *data; + int ret = -ENODEV; + int status; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as9716_32d_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + + /* Register sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + case as9716_32d_cpld_cpu: + /* Disable CPLD reset to avoid DUT will be reset. + */ + status=as9716_32d_cpld_write_internal(client, 0x3, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpu_cpld reg 0x65 err %d\n", status); + } + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as9716_32d_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as9716_32d_cpld_remove(struct i2c_client *client) +{ + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as9716_32d_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_read); + +int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_write); + +static struct i2c_driver as9716_32d_cpld_driver = { + .driver = { + .name = "as9716_32d_cpld", + .owner = THIS_MODULE, + }, + .probe = as9716_32d_cpld_probe, + .remove = as9716_32d_cpld_remove, + .id_table = as9716_32d_cpld_id, +}; + +static int __init as9716_32d_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as9716_32d_cpld_driver); +} + +static void __exit as9716_32d_cpld_exit(void) +{ + i2c_del_driver(&as9716_32d_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as9716_32d_cpld_init); +module_exit(as9716_32d_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c new file mode 100755 index 000000000000..4d2433e7981e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c @@ -0,0 +1,760 @@ +/* + * A hwmon driver for the Accton as9716 32d fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9716_32d_fan" + +#define NUM_THERMAL_SENSORS (7) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4c , 0x4e} + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as9716_32d_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) + +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); + +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as9716_32d_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as9716_32d_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as9716_32d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as9716_32d_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as9716_32d_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as9716_32d_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as9716_32d_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as9716_32d_fan_group = { + .attrs = as9716_32d_fan_attributes, +}; + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as9716_32d_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as9716_32d_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as9716_32d_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_fan_remove(struct i2c_client *client) +{ + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as9716_32d_fan_id[] = { + { "as9716_32d_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_fan_id); + +static struct i2c_driver as9716_32d_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as9716_32d_fan_probe, + .remove = as9716_32d_fan_remove, + .id_table = as9716_32d_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as9716_32d_fan_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c new file mode 100755 index 000000000000..0fd28a4631b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c @@ -0,0 +1,492 @@ +/* + * A LED driver for the accton_as9716_32d_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as9716_32d_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_as9716_32d_led" + +struct accton_as9716_32d_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* only 1 register*/ +}; + +static struct accton_as9716_32d_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x61) + +#define LED_TYPE_DIAG_REG_MASK (0x1|0x2|0x4) +#define LED_MODE_DIAG_GREEN_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x02) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0) + + +#define LED_TYPE_LOC_REG_MASK (0x80|0x40) +#define LED_MODE_LOC_GREEN_BLIKN_VALUE 0x80 +#define LED_MODE_LOC_AMBER_VALUE 0x40 +#define LED_MODE_LOC_OFF_VALUE (0x0) + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_AMBER_VALUE 0x20 +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) +#define LED_MODE_PSU2_AMBER_VALUE 0x8 +#define LED_MODE_PSU2_GREEN_VALUE 0x4 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) +#define LED_MODE_PSU1_AMBER_VALUE 0x2 +#define LED_MODE_PSU1_GREEN_VALUE 0x1 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as9716_32d_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as9716_32d_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as9716_32d_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as9716_32d_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_as9716_32d_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as9716_32d_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as9716_32d_led_diag_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as9716_32d_led_loc_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_as9716_32d_led_fan_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_as9716_32d_led_psu1_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_as9716_32d_led_psu2_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static struct led_classdev accton_as9716_32d_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as9716_32d_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_diag_set, + .brightness_get = accton_as9716_32d_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "accton_as9716_32d_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_loc_set, + .brightness_get = accton_as9716_32d_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "accton_as9716_32d_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_fan_set, + .brightness_get = accton_as9716_32d_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as9716_32d_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu1_set, + .brightness_get = accton_as9716_32d_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as9716_32d_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu2_set, + .brightness_get = accton_as9716_32d_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, +}; + +static int accton_as9716_32d_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_suspend(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_resume(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as9716_32d_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as9716_32d_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + } + + return ret; +} + +static int accton_as9716_32d_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as9716_32d_led_driver = { + .probe = accton_as9716_32d_led_probe, + .remove = accton_as9716_32d_led_remove, + .suspend = accton_as9716_32d_led_suspend, + .resume = accton_as9716_32d_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as9716_32d_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as9716_32d_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as9716_32d_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as9716_32d_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as9716_32d_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); +} + +module_init(accton_as9716_32d_led_init); +module_exit(accton_as9716_32d_led_exit); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("accton_as9716_32d_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c new file mode 100755 index 000000000000..06e8e23c3c53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c @@ -0,0 +1,311 @@ +/* + * An hwmon driver for accton as9716_32d Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as9716_32d_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER]; +}; + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev); + +enum as9716_32d_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as9716_32d_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as9716_32d_psu_group = { + .attrs = as9716_32d_psu_attributes, +}; + +static int as9716_32d_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_psu_remove(struct i2c_client *client) +{ + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as9716_32d_psu1, + as9716_32d_psu2 +}; + +static const struct i2c_device_id as9716_32d_psu_id[] = { + { "as9716_32d_psu1", as9716_32d_psu1 }, + { "as9716_32d_psu2", as9716_32d_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_psu_id); + +static struct i2c_driver as9716_32d_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as9716_32d_psu", + }, + .probe = as9716_32d_psu_probe, + .remove = as9716_32d_psu_remove, + .id_table = as9716_32d_psu_id, + .address_list = normal_i2c, +}; + +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as9716_32d update\n"); + + /* Read psu status */ + status = as9716_32d_cpld_read(0x60, 0x3); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as9716_32d_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as9716_32d_psu_read_block(client, 0x2e,data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as9716_32d_psu_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c new file mode 100755 index 000000000000..df7324de5604 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c @@ -0,0 +1,602 @@ +/* + * An hwmon driver for the Accton Redundant Power Module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" +/* PMBus Protocol. */ +#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 +#define PMBUS_REGISTER_VOUT_MODE 0x20 +#define PMBUS_REGISTER_STATUS_BYTE 0x78 +#define PMBUS_REGISTER_STATUS_WORD 0x79 +#define PMBUS_REGISTER_STATUS_FAN 0x81 +#define PMBUS_REGISTER_READ_VIN 0x88 +#define PMBUS_REGISTER_READ_IIN 0x89 +#define PMBUS_REGISTER_READ_VOUT 0x8B +#define PMBUS_REGISTER_READ_IOUT 0x8C +#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D +#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E +#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F +#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 +#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 + +#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A +#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B + +#define PMBUS_REGISTER_READ_POUT 0x96 +#define PMBUS_REGISTER_READ_PIN 0x97 +#define PMBUS_REGISTER_MFR_ID 0x99 +#define PMBUS_REGISTER_MFR_MODEL 0x9A +#define PMBUS_REGISTER_MFR_REVISION 0x9B +#define PMBUS_REGISTER_MFR_SERIAL 0x9E + + +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct accton_i2c_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u8 mfr_serial[26]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); + +enum accton_i2c_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT_UV, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_SERIAL, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +//static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + + +static struct attribute *accton_i2c_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + //&sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 0; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier=1; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + if(!multiplier) + multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; + if(attr->index==PSU_P_OUT_UV) + multiplier = 1000000; + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + int exponent, mantissa; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : + sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); +} + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + switch (attr->index) { + + case PSU_MFR_ID: + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: + ptr = data->mfr_revsion; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + + +static const struct attribute_group accton_i2c_psu_group = { + .attrs = accton_i2c_psu_attributes, +}; + +static int accton_i2c_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct accton_i2c_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int accton_i2c_psu_remove(struct i2c_client *client) +{ + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); + kfree(data); + + return 0; +} +/* Support psu moduel + */ +static const struct i2c_device_id accton_i2c_psu_id[] = { + { "acbel_fsh082", 0 }, + { "yesm1300am", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); + +static struct i2c_driver accton_i2c_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_psu", + }, + .probe = accton_i2c_psu_probe, + .remove = accton_i2c_psu_remove, + .id_table = accton_i2c_psu_id, + .address_list = normal_i2c, +}; + +static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) +{ + int status = -EIO; + int length; + u8 buffer[128] = {0}, *ptr = buffer; + + status = accton_i2c_psu_read_byte(client, command); + if (status < 0) + { + dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + + status = (status & 0xFF) + 1; + if ( status > 128) + { + dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); + status = -EINVAL; + goto EXIT_READ_BLOCK_DATA; + } + + length = status; + status = accton_i2c_psu_read_block(client, command, buffer, length); + if (unlikely(status < 0)) + goto EXIT_READ_BLOCK_DATA; + if (unlikely(status != length)) { + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + /* The first byte is the count byte of string. */ + ptr++; + status--; + + length=status>(data_length-1)?(data_length-1):status; + memcpy(data, ptr, length); + data[length-1] = 0; + +EXIT_READ_BLOCK_DATA: + + return status; +} + + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + //u8 command, buf; + struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, + {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, + {PMBUS_REGISTER_READ_VOUT, &data->v_out}, + {PMBUS_REGISTER_READ_IIN, &data->i_in}, + {PMBUS_REGISTER_READ_IOUT, &data->i_out}, + {PMBUS_REGISTER_READ_POUT, &data->p_out}, + {PMBUS_REGISTER_READ_PIN, &data->p_in}, + {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, + {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, + {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, + }; + + dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = accton_i2c_psu_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + + } + /* Read mfr_id */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, + ARRAY_SIZE(data->mfr_id)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); + goto exit; + } + /* Read mfr_model */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, + ARRAY_SIZE(data->mfr_model)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); + goto exit; + } + /* Read mfr_revsion */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); + goto exit; + } + /* Read mfr_serial */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, + ARRAY_SIZE(data->mfr_serial)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init accton_i2c_psu_init(void) +{ + return i2c_add_driver(&accton_i2c_psu_driver); +} + +static void __exit accton_i2c_psu_exit(void) +{ + i2c_del_driver(&accton_i2c_psu_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_psu_init); +module_exit(accton_i2c_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service new file mode 100755 index 000000000000..b77b40d67299 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring FAN service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service new file mode 100755 index 000000000000..69bcf37e27f5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring PSU service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service new file mode 100755 index 000000000000..1d77c39120a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as9716_32d_util.py install +ExecStart=/usr/local/bin/accton_as9716_32d_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py new file mode 100755 index 000000000000..7c70492e5d6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as9716_32d', + version='1.0', + description='Module to initialize Accton AS9716-32D platforms', + + packages=['as9716_32d'], + package_dir={'as9716_32d': 'as9716-32d/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program 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, either version 3 of the License, or +(at your option) any later version. + +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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py new file mode 100755 index 000000000000..f80c1223a83c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 12/19/2018:Jostar create for as9716_32d thermal plan +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from as9716_32d.fanutil import FanUtil + from as9716_32d.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32x_monitor' + +global log_file +global log_level + + +# Air Flow Front to Back : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system +# One Fan fail : Change Fan speed to 100%(0x0E) + + +# Air Flow Back to Front : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system +# One Fan fail: Change Fan speed to 100%(0x0E) +# sensor_LM75_CPU == sensor_LM75_4B + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] +temp_test_data=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2]) + if temp > policy[i][2]: + if temp <= policy[i][3]: + state =i + logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) + logging.debug ('fan_state=%d', state) + break + + return state + + + def manage_fans(self): + + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + global temp_test_data + + LEVEL_FAN_DEF=0 + LEVEL_FAN_MID=1 + LEVEL_FAN_MAX=2 + LEVEL_TEMP_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + + + fan_policy_f2b = { + LEVEL_FAN_DEF: [38, 0x4, 0, 38000], + LEVEL_FAN_MID: [63, 0x6, 38000, 46000], + LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], + LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], + } + fan_policy_b2f = { + LEVEL_FAN_DEF: [38, 0x4, 0, 34000], + LEVEL_FAN_MID: [63, 0x8, 34000, 44000], + LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], + LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], + } + + fan_policy = fan_policy_f2b + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_dri=1 #something wrong, set fan_dir to default val + else: + fan_policy = fan_policy_b2f + + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + fan_fail=0 + + if temp3==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp4==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 + ori_state=fan_policy_state + + #temp_test_data=temp_test_data+1000 + #temp_get = temp_get + temp_test_data + #print "Unit test:temp_get=%d"%temp_get + + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + #print "temp3=%d"%temp3 + #print "temp4=%d"%temp4 + #print "temp_get=%d"%temp_get + + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_fan_cycle=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + #if fan_policy_state == ori_state: + # return True + #else: + new_state = fan_policy_state + + #logging.warning('Temperature high alarm testing') + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=7: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 7): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + #monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py new file mode 100755 index 000000000000..320655361b83 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/13/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/17-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py new file mode 100755 index 000000000000..a8df99430c81 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/12/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "9-0050", + 1: "10-0051", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py new file mode 100755 index 000000000000..e9779db01d2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py @@ -0,0 +1,571 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +PROJECT_NAME = 'as9716_32d' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':34} + + +led_prefix ='/sys/devices/platform/as9716_32d_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as9716_32d_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + 'fan6': ['fan_duty_cycle_percentage','fan6_fault', 'fan6_speed_rpm', 'fan6_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['18-0048', '18-0049','18-004a', '18-004b', '18-004c', '18-004e', '18-004f'] , + 'psu': ['9-0058', '10-0059'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58] + +#sfp_map = [25, 26] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', + +'echo as9716_32d_fpga 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo as9716_32d_cpld1 0x61 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo as9716_32d_cpld2 0x62 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as9716_32d_cpld_cpu 0x65 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as9716_32d_fan 0x66 > /sys/bus/i2c/devices/i2c-17/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4f > /sys/bus/i2c/devices/i2c-18/new_device', + +# PSU-1 +'echo as9716_32d_psu1 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo acbel_fsh082 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', + +# PSU-2 +'echo as9716_32d_psu2 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo acbel_fsh082 0x59 > /sys/bus/i2c/devices/i2c-10/new_device', + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) > DEVICE_NO['sfp'] -1: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_psu', +'modprobe accton_as9716_32d_cpld', +'modprobe accton_as9716_32d_fan', +'modprobe accton_as9716_32d_leds', +'modprobe accton_as9716_32d_psu', +'modprobe optoe', +'modprobe lm75'] + +cpld_reset_stop='i2cset -y 0 0x65 0x3 0x0' + +def driver_install(): + + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + log_os_system(cpld_reset_stop, 1) + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + print "init i2c device instance" + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + #if len(ALL_DEVICE)==0: + # devices_info() + #node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + #node = node.replace(node.split("/")[-1], 'eeprom') + node= "/sys/bus/i2c/devices/"+str(sfp_map[int(index)])+"-0050" + "/eeprom" + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + #print node + ":" + #ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + ret, log = log_os_system(hex_cmd+" -C " + node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index 1a36758a0fb9..49ce40068358 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -1,7 +1,7 @@ Source: sonic-accton-platform-modules Section: main Priority: extra -Maintainer: Accton network , Accton Network +Maintainer: Accton network , Accton Network , Accton Network , Accton Network Build-Depends: debhelper (>= 9), bzip2 Standards-Version: 3.9.3 @@ -57,3 +57,7 @@ Package: sonic-platform-accton-as5835-54x Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp +Package: sonic-platform-accton-as9716-32d +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index 60cec5ab13e5..46014874d5c0 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x +MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service From a893a6840e4262aa28e64cfb362566870d40f648 Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 17 Jul 2019 11:16:29 +0800 Subject: [PATCH 5/7] Add support build as9716 platform to mk file --- platform/broadcom/one-image.mk | 1 + platform/broadcom/platform-modules-accton.mk | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index db9acc0cc30a..d17dcfe067d7 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -26,6 +26,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_MINIPACK_PLATFORM_MODULE) \ $(ACCTON_AS5812_54X_PLATFORM_MODULE) \ $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ + $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index 7b6ae093b8d1..ebf76bbd716d 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -13,6 +13,7 @@ ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1 ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -27,6 +28,7 @@ export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton @@ -83,5 +85,8 @@ ACCTON_AS5835_54X_PLATFORM_MODULE = sonic-platform-accton-as5835-54x_$(ACCTON_AS $(ACCTON_AS5835_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54x-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54X_PLATFORM_MODULE))) +ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE))) SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) From 4c21d0ae87bde452df4658e610743f4de83c62b3 Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 17 Jul 2019 11:50:34 +0800 Subject: [PATCH 6/7] Add support AS5835_54T platform --- platform/broadcom/one-image.mk | 1 + platform/broadcom/platform-modules-accton.mk | 6 + .../as5835-54t/classes/__init__.py | 0 .../as5835-54t/classes/fanutil.py | 237 +++++++ .../as5835-54t/classes/thermalutil.py | 129 ++++ .../as5835-54t/modules/Makefile | 17 + .../modules/accton_as5835_54t_cpld.c | 603 ++++++++++++++++++ .../modules/accton_as5835_54t_fan.c | 484 ++++++++++++++ .../modules/accton_as5835_54t_leds.c | 380 +++++++++++ .../modules/accton_as5835_54t_psu.c | 343 ++++++++++ .../as5835-54t/modules/ym2651y.c | 1 + .../as5835-54t-platform-monitor-fan.service | 16 + .../as5835-54t-platform-monitor-psu.service | 16 + .../as5835-54t-platform-monitor.service | 18 + .../as5835-54t/setup.py | 16 + .../as5835-54t/utils/README | 74 +++ .../utils/accton_as5835_54t_monitor.py | 206 ++++++ .../utils/accton_as5835_54t_monitor_fan.py | 198 ++++++ .../utils/accton_as5835_54t_monitor_psu.py | 190 ++++++ .../utils/accton_as5835_54t_util.py | 576 +++++++++++++++++ .../debian/control | 3 + .../debian/rules | 2 +- 22 files changed, 3515 insertions(+), 1 deletion(-) create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c create mode 120000 platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README create mode 100755 platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index d17dcfe067d7..b1e34e88f03f 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -27,6 +27,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_AS5812_54X_PLATFORM_MODULE) \ $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ + $(ACCTON_AS5835_54T_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index ebf76bbd716d..af8cb0fb4701 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -14,6 +14,7 @@ ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -29,6 +30,7 @@ export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION +export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton @@ -89,4 +91,8 @@ ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS $(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE))) +ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE))) + SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py new file mode 100644 index 000000000000..c741ebfd7246 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0063/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0063/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py new file mode 100644 index 000000000000..1dc97cfe276d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 6/11/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 # 1_ON_CPU_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['18', '4b'], + THERMAL_NUM_2_IDX: ['19', '4c'], + THERMAL_NUM_3_IDX: ['20', '49'], + THERMAL_NUM_4_IDX: ['21', '4a'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon3/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/19-004c/hwmon/hwmon4/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/20-0049/hwmon/hwmon5/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/21-004a/hwmon/hwmon6/temp1_input"], + } + + #def __init__(self): + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + if(os.path.isfile(device_path)): + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + print "No such device_path=%s"%device_path + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_3_val(self): + return self._get_thermal_val(self.THERMAL_NUM_3_IDX) + + def get_thermal_temp(self): + return (self._get_thermal_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile new file mode 100644 index 000000000000..887ac3189cec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as5835_54t_cpld.o accton_as5835_54t_psu.o \ + accton_as5835_54t_fan.o accton_as5835_54t_leds.o \ + ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c new file mode 100644 index 000000000000..ae773b4d8209 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c @@ -0,0 +1,603 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5835_54t CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954t.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954t.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as5835_54t_cpld1, + as5835_54t_cpld2, + as5835_54t_cpld3 +}; + +struct as5835_54t_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5835_54t_cpld_id[] = { + { "as5835_54t_cpld1", as5835_54t_cpld1 }, + { "as5835_54t_cpld2", as5835_54t_cpld2 }, + { "as5835_54t_cpld3", as5835_54t_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as5835_54t_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_LPMODE_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_RESET_##index) +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_lpmode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5835_54t_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5835_54t_cpld1_group = { + .attrs = as5835_54t_cpld1_attributes, +}; + +static struct attribute *as5835_54t_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + NULL +}; + +static const struct attribute_group as5835_54t_cpld2_group = { + .attrs = as5835_54t_cpld2_attributes, +}; + +static struct attribute *as5835_54t_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5835_54t_cpld3_group = { + .attrs = as5835_54t_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs_cpld3[] = {0x14}; + u8 *regs[] = {NULL, NULL, regs_cpld3}; + u8 size[] = {0, 0, ARRAY_SIZE(regs_cpld3)}; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as5835_54t_cpld_read_internal(client, regs[data->type][i]); + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + values[0] &= 0x3F; + return sprintf(buf, "%.2x\n", values[0]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_49 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable/lpmode/reset status */ + if (value) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5835_54t_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as5835_54t_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5835_54t_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5835_54t_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5835_54t_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as5835_54t_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as5835_54t_cpld1: + group = &as5835_54t_cpld1_group; + break; + case as5835_54t_cpld2: + group = &as5835_54t_cpld2_group; + break; + case as5835_54t_cpld3: + group = &as5835_54t_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5835_54t_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5835_54t_cpld_remove(struct i2c_client *client) +{ + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5835_54t_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5835_54t_cpld1: + group = &as5835_54t_cpld1_group; + break; + case as5835_54t_cpld2: + group = &as5835_54t_cpld2_group; + break; + case as5835_54t_cpld3: + group = &as5835_54t_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54t_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54t_cpld_read); + +int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54t_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54t_cpld_write); + +static struct i2c_driver as5835_54t_cpld_driver = { + .driver = { + .name = "as5835_54t_cpld", + .owner = THIS_MODULE, + }, + .probe = as5835_54t_cpld_probe, + .remove = as5835_54t_cpld_remove, + .id_table = as5835_54t_cpld_id, +}; + +static int __init as5835_54t_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5835_54t_cpld_driver); +} + +static void __exit as5835_54t_cpld_exit(void) +{ + i2c_del_driver(&as5835_54t_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5835_54t_cpld_init); +module_exit(as5835_54t_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c new file mode 100644 index 000000000000..ea6fdb8296c9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c @@ -0,0 +1,484 @@ +/* + * A hwmon driver for the Accton as5835 54t fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54t_fan" +#define MAX_FAN_SPEED_RPM 21500 + +static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x02, /* fan 1-5 present status */ + 0x03, /* fan 1-5 direction(0:F2B 1:B2F) */ + 0x04, /* front fan 1-5 fault status */ + 0x05, /* rear fan 1-5 fault status */ + 0x06, /* fan PWM(for all fan) */ + 0x07, /* front fan 1 speed(rpm) */ + 0x08, /* front fan 2 speed(rpm) */ + 0x09, /* front fan 3 speed(rpm) */ + 0x0A, /* front fan 4 speed(rpm) */ + 0x0B, /* front fan 5 speed(rpm) */ + 0x0C, /* rear fan 1 speed(rpm) */ + 0x0D, /* rear fan 2 speed(rpm) */ + 0x0E, /* rear fan 3 speed(rpm) */ + 0x0F, /* rear fan 4 speed(rpm) */ + 0x10, /* rear fan 5 speed(rpm) */ +}; + +/* fan data */ +struct as5835_54t_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN_MAX_RPM, + CPLD_VERSION +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM); +#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5, 15); +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5, 15); +/* 5 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 5 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +static struct attribute *as5835_54t_fan_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1, 11), + DECLARE_FAN_FAULT_ATTR(2, 12), + DECLARE_FAN_FAULT_ATTR(3, 13), + DECLARE_FAN_FAULT_ATTR(4, 14), + DECLARE_FAN_FAULT_ATTR(5, 15), + DECLARE_FAN_SPEED_RPM_ATTR(1, 11), + DECLARE_FAN_SPEED_RPM_ATTR(2, 12), + DECLARE_FAN_SPEED_RPM_ATTR(3, 13), + DECLARE_FAN_SPEED_RPM_ATTR(4, 14), + DECLARE_FAN_SPEED_RPM_ATTR(5, 15), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_MAX_RPM_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as5835_54t_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as5835_54t_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle > FAN_MAX_DUTY_CYCLE) { + duty_cycle = FAN_MAX_DUTY_CYCLE; + } + + return (duty_cycle / 5); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & BIT(id)); /* 0: Front to Back, 1: Back to Front*/ +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + return !(reg_val & BIT(id)); +} + +static u8 is_fan_fault(struct as5835_54t_fan_data *data, enum fan_id id) +{ + if ((data->reg_val[FAN_FRONT_FAULT_REG] & BIT(id)) || + (data->reg_val[FAN_REAR_FAULT_REG] & BIT(id))) { + return 1; + } + + return 0; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) { + return error; + } + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) { + return -EINVAL; + } + + as5835_54t_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_fan_data *data = as5835_54t_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + case FAN_MAX_RPM: + ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM); + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as5835_54t_fan_group = { + .attrs = as5835_54t_fan_attributes, +}; + +static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as5835_54t_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as5835_54t_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static int as5835_54t_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54t_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54t_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54t_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_fan", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54t_fan_remove(struct i2c_client *client) +{ + struct as5835_54t_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as5835_54t_fan_id[] = { + { "as5835_54t_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_fan_id); + +static struct i2c_driver as5835_54t_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as5835_54t_fan_probe, + .remove = as5835_54t_fan_remove, + .id_table = as5835_54t_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as5835_54t_fan_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54t_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c new file mode 100644 index 000000000000..e02930a2f6e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c @@ -0,0 +1,380 @@ +/* + * A LED driver for the accton_as5822_54t_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54t_led" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct accton_as5835_54t_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED, + 1 = FAN/PSU LED, + 2 ~ 4 = SYSTEM LED */ +}; + +static struct accton_as5835_54t_led_data *ledctl = NULL; + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x0C) +#define LED_MODE_DIAG_GREEN_VALUE (0x08) +#define LED_MODE_DIAG_AMBER_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0C) +#define LED_MODE_DIAG_AMBER_VALUE1 (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x30) +#define LED_MODE_LOC_AMBER_BLINK_VALUE (0x20) +#define LED_MODE_LOC_OFF_VALUE (0x10) +#define LED_MODE_LOC_AMBER_VALUE (0x00) + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED */ + 0xB, /* PSU LED */ +}; + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +/* FAN/PSU/DIAG/RELEASE led mode */ +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINK_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE1}, +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int accton_as5835_54t_led_read_value(u8 reg) +{ + return as5835_54t_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int accton_as5835_54t_led_write_value(u8 reg, u8 value) +{ + return as5835_54t_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void accton_as5835_54t_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5835_54t_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5835_54t_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + ledctl->reg_val[i] = status; + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5835_54t_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + reg_val = accton_as5835_54t_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5835_54t_led_write_value(reg, reg_val); + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54t_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54t_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static void accton_as5835_54t_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5835_54t_led_diag_get(struct led_classdev *cdev) +{ + accton_as5835_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static enum led_brightness accton_as5835_54t_led_loc_get(struct led_classdev *cdev) +{ + accton_as5835_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as5835_54t_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static struct led_classdev accton_as5835_54t_leds[] = { + [LED_TYPE_LOC] = { + .name = "as5835_54t_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5835_54t_led_loc_set, + .brightness_get = accton_as5835_54t_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_DIAG] = { + .name = "as5835_54t_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5835_54t_led_diag_set, + .brightness_get = accton_as5835_54t_led_diag_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "as5835_54t_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as5835_54t_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "as5835_54t_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5835_54t_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5835_54t_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5835_54t_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5835_54t_leds[i]); + } + } + + return ret; +} + +static int accton_as5835_54t_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) { + led_classdev_unregister(&accton_as5835_54t_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5835_54t_led_driver = { + .probe = accton_as5835_54t_led_probe, + .remove = accton_as5835_54t_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5835_54t_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5835_54t_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5835_54t_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&accton_as5835_54t_led_driver); +exit: + return ret; +} + +static void __exit accton_as5835_54t_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5835_54t_led_driver); + kfree(ledctl); +} + +late_initcall(accton_as5835_54t_led_init); +module_exit(accton_as5835_54t_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5835_54t_led driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c new file mode 100644 index 000000000000..78f0b4298a58 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c @@ -0,0 +1,343 @@ +/* + * An hwmon driver for accton as5835_54t Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define MODEL_NAME_LEN 8 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5835_54t_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev); + +enum as5835_54t_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as5835_54t_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_numer.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev); + char *str = NULL; + + if (!data->valid) { + return 0; + } + + if (attr->index == PSU_MODEL_NAME) { + str = data->model_name; + } + else { /* PSU_SERIAL_NUBMER */ + str = data->serial; + } + + return sprintf(buf, "%s\n", str); +} + +static const struct attribute_group as5835_54t_psu_group = { + .attrs = as5835_54t_psu_attributes, +}; + +static int as5835_54t_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54t_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54t_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54t_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_psu", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54t_psu_remove(struct i2c_client *client) +{ + struct as5835_54t_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5835_54t_psu1, + as5835_54t_psu2 +}; + +static const struct i2c_device_id as5835_54t_psu_id[] = { + { "as5835_54t_psu1", as5835_54t_psu1 }, + { "as5835_54t_psu2", as5835_54t_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_psu_id); + +static struct i2c_driver as5835_54t_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5835_54t_psu", + }, + .probe = as5835_54t_psu_probe, + .remove = as5835_54t_psu_remove, + .id_table = as5835_54t_psu_id, + .address_list = normal_i2c, +}; + +static int as5835_54t_psu_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int status = 0; + int retry_count = 5; + + while (retry_count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(10); + retry_count--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + +abort: + return status; +} + +static int as5835_54t_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as5835_54t_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + dev_dbg(&client->dev, "Starting as5835_54t update\n"); + data->valid = 0; + + /* Read psu status */ + status = as5835_54t_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (IS_PRESENT(data->index, data->status)) { + /* Read model name */ + status = as5835_54t_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + + /* Read serial number */ + status = as5835_54t_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[SERIAL_NUM_LEN] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5835_54t_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54t_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service new file mode 100644 index 000000000000..19ad3e519471 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring FAN service +Before=pmon.service +After=as5835-54t-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54t_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service new file mode 100644 index 000000000000..f30b13b6bc3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring PSU service +Before=pmon.service +After=as5835-54t-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54t_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service new file mode 100644 index 000000000000..9789201034c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as5835_54t_util.py install +ExecStart=/usr/local/bin/accton_as5835_54t_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py new file mode 100644 index 000000000000..ac880c41e4e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5835_54t', + version='1.0', + description='Module to initialize Accton AS5835-54T platforms', + + packages=['as5835_54t'], + package_dir={'as5835_54t': 'as5835-54t/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README new file mode 100644 index 000000000000..dc9b838f9f1b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program 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, either version 3 of the License, or +(at your option) any later version. + +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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as5835 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5835-54T has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as5835_54t_util.py, for device initializatian. + Run "accton_as5835_54t_util.py install" to install drivers. + +To initialize the system, run "accton_as5835_54t_util.py install". +To clean up the drivers & devices, run "accton_as5835_54t_util.py clean". +To dump information of sensors, run "accton_as5835_54t_util.py show". +To dump SFP EEPROM, run "accton_as5835_54t_util.py sff". +To set fan speed, run "accton_as5835_54t_util.py set fan". +To enable/disable SFP emission, run "accton_as5835_54t_util.py set sfp". +To set system LEDs' color, run "accton_as5835_54t_util.py set led" +For more information, run "accton_as5835_54t_util.py --help". + +==================================================================== +Besides applying accton_as5835_54t_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => green blinking + 3 => amber + 4 => amber blinking + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 4 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py new file mode 100755 index 000000000000..ce2e0d18d4ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5812-54x. +# 05/29/2019: Brandon Chuang, changed for as5835-54x. +# 06/11/2019: Brandon Chuang, changed for as5835-54t. +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + import signal + from tabulate import tabulate + from as5835_54t.fanutil import FanUtil + from as5835_54t.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5835_54t_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5835_54t_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + temp3 = thermal.get_thermal_3_val() + if temp3 is None: + return False + + new_temp = (temp2 + temp3) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None: + return False + if fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + logging.debug('INFO. fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle() + if cur_perc == self._new_perc: + logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(self._new_perc) + if set_stat is True: + logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as5835_54t_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py new file mode 100755 index 000000000000..d1d93d4f8aea --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + #/sys/bus/i2c/devices/3-0063 + #fan1_present, fan5_present + + def __init__(self, log_file, log_level): + + self.fan_num = 5 + self.fan_path = "/sys/bus/i2c/devices/3-0063/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py new file mode 100755 index 000000000000..51837c7262ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_psu' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +psu_state=[2, 2] +psu_power_status=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "11-0050", + 1: "12-0053", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + + global psu_state + global psu_power_status + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=PSU_STATE_INSERT: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=PSU_STATE_REMOVE: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]); + if content == "0": + if psu_power_status[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d fault is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + else: + if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py new file mode 100755 index 000000000000..a07ab1a1bc7e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py @@ -0,0 +1,576 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Networks, Inc. +# +# This program 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as5835_54t' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':6} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 49-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[Debug]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_as5835_54t_cpld' , +'modprobe ym2651y' , +'modprobe accton_as5835_54t_fan' , +'modprobe optoe' , +'modprobe accton_as5835_54t_leds' , +'modprobe accton_as5835_54t_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['3-0063'] , + 'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] , + 'psu': ['11-0050','12-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'module_tx_disable_']} + +sfp_map = [28,29,26,30,31,27] + +qsfp_start = 48 + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + +mknod2 =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x77 is exist @ i2c-1 + tmp = "echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x77 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x77 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + time.sleep(0.01) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + path = "/sys/bus/i2c/devices/{0}-0050/port_name" + status, output =log_os_system("echo port{0} > ".format(i+49)+path.format(sfp_map[i]), 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0077", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~5 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index 49ce40068358..8100f6b76e16 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -61,3 +61,6 @@ Package: sonic-platform-accton-as9716-32d Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp +Package: sonic-platform-accton-as5835-54t +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index 46014874d5c0..ba2f3e394d1d 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d +MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d as5835-54t MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service From 5b4906e2925e9a1b51c6ad00944f6749a9bcfb85 Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Fri, 25 Oct 2019 18:02:52 +0800 Subject: [PATCH 7/7] Add thermal plan to as4630_54pe --- .../as4630-54pe/classes/fanutil.py | 257 ++++----------- .../as4630-54pe/classes/thermalutil.py | 105 +++---- .../utils/accton_as4630_54pe_monitor.py | 294 +++++++----------- 3 files changed, 206 insertions(+), 450 deletions(-) diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py index b6752783dc03..df2e511adef7 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py @@ -1,223 +1,90 @@ #!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation # -# Copyright (C) 2017 Accton Technology Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # -# This program 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, either version 3 of the License, or -# (at your option) any later version. +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. # -# 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. +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - # ------------------------------------------------------------------ # HISTORY: # mm/dd/yyyy (A.D.) -# 11/13/2017: Polly Hsu, Create -# 1/10/2018: Jostar modify for as7716_32 -# 12/03/2018: Jostar modify for as7726_32 +# 10/24/2019:Jostar craete for as4630_54pe # ------------------------------------------------------------------ try: + import os import time import logging + import glob + import commands from collections import namedtuple except ImportError as e: raise ImportError('%s - required module not found' % str(e)) - -class FanUtil(object): - """Platform-specific FanUtil class""" - - FAN_NUM_ON_MAIN_BROAD = 6 - FAN_NUM_1_IDX = 1 - FAN_NUM_2_IDX = 2 - FAN_NUM_3_IDX = 3 - FAN_NUM_4_IDX = 4 - FAN_NUM_5_IDX = 5 - FAN_NUM_6_IDX = 6 - - FAN_NODE_NUM_OF_MAP = 2 - FAN_NODE_FAULT_IDX_OF_MAP = 1 - FAN_NODE_DIR_IDX_OF_MAP = 2 +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 + THERMAL_NUM_2_IDX = 2 + THERMAL_NUM_3_IDX = 3 + THERMAL_NUM_4_IDX = 4 - BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' - FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' - - #logfile = '' - #loglevel = logging.INFO - """ Dictionary where - key1 = fan id index (integer) starting from 1 - key2 = fan node index (interger) starting from 1 + key1 = thermal id index (integer) starting from 1 value = path to fan device file (string) """ - _fan_to_device_path_mapping = {} - -#fan1_direction -#fan1_fault -#fan1_present - - #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', - _fan_to_device_node_mapping = { - (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', - (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', - - (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', - (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', - - (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', - (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', - - (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', - (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', - - (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', - (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/24-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/25-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/class/hwmon/hwmon1/temp1_input"], + } - (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', - (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', - } - - def _get_fan_to_device_node(self, fan_num, node_num): - return self._fan_to_device_node_mapping[(fan_num, node_num)] - - def _get_fan_node_val(self, fan_num, node_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) - return None - - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) return None - - device_path = self.get_fan_to_device_path(fan_num, node_num) - try: - val_file = open(device_path, 'r') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None - - content = val_file.readline().rstrip() - - if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) - return None - - try: - val_file.close() - except: - logging.debug('GET. unable to close file. device_path:%s', device_path) - return None - - return int(content) - - def _set_fan_node_val(self, fan_num, node_num, val): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) - return None - - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) - return None - - content = str(val) - if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) - return None - - device_path = self.get_fan_to_device_path(fan_num, node_num) - try: - val_file = open(device_path, 'w') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None - - val_file.write(content) - - try: - val_file.close() - except: - logging.debug('GET. unable to close file. device_path:%s', device_path) - return None - - return True - - def __init__(self): - fan_path = self.BASE_VAL_PATH - - for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): - for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): - self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( - self._fan_to_device_node_mapping[(fan_num, node_num)]) - - def get_num_fans(self): - return self.FAN_NUM_ON_MAIN_BROAD - - def get_idx_fan_start(self): - return self.FAN_NUM_1_IDX - - def get_num_nodes(self): - return self.FAN_NODE_NUM_OF_MAP - - def get_idx_node_start(self): - return self.FAN_NODE_FAULT_IDX_OF_MAP + device_path = self.get_thermal_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 - def get_size_node_map(self): - return len(self._fan_to_device_node_mapping) + def get_num_thermals(self): + return self.THERMAL_NUM_MAX def get_size_path_map(self): - return len(self._fan_to_device_path_mapping) - - def get_fan_to_device_path(self, fan_num, node_num): - return self._fan_to_device_path_mapping[(fan_num, node_num)] - - def get_fan_fault(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) - - - def get_fan_dir(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) - - def get_fan_duty_cycle(self): - #duty_path = self.FAN_DUTY_PATH - try: - val_file = open(self.FAN_DUTY_PATH) - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - - content = val_file.readline().rstrip() - val_file.close() - return int(content) + return len(self.thermal_sysfspath) - def set_fan_duty_cycle(self, val): - try: - fan_file = open(self.FAN_DUTY_PATH, 'r+') - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - #val = ((val + 1 ) * 625 +75 ) / 100 - fan_file.write(str(val)) - fan_file.close() - return True - - def get_fanr_speed(self, fan_num): - return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) - - def get_fan_status(self, fan_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num, %d', fan_num) - return None - - if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: - logging.debug('GET. FAN fault. fan_num, %d', fan_num) - return False - - return True + def get_thermal_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] +def main(): + thermal = ThermalUtil() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py index 3af7b3d7df5f..bd5530fd9035 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py @@ -1,26 +1,22 @@ #!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation # -# Copyright (C) 2017 Accton Technology Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # -# This program 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, either version 3 of the License, or -# (at your option) any later version. +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. # -# 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. +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - # ------------------------------------------------------------------ # HISTORY: # mm/dd/yyyy (A.D.) -# 11/13/2017: Polly Hsu, Create -# 1/10/2018:Jostar modify for as7716_32x -# 12/03/2018:Jostar modify for as7726_32x thermal plan +# 10/24/2019:Jostar craete for as4630_54pe # ------------------------------------------------------------------ try: @@ -35,91 +31,60 @@ class ThermalUtil(object): """Platform-specific ThermalUtil class""" - THERMAL_NUM_MAX = 5 - THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 - THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 - THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 - THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 - THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 + THERMAL_NUM_2_IDX = 2 + THERMAL_NUM_3_IDX = 3 + THERMAL_NUM_4_IDX = 4 """ Dictionary where key1 = thermal id index (integer) starting from 1 value = path to fan device file (string) """ - - _thermal_to_device_node_mapping = { - THERMAL_NUM_1_IDX: ['55', '48'], - THERMAL_NUM_2_IDX: ['55', '49'], - THERMAL_NUM_3_IDX: ['55', '4a'], - THERMAL_NUM_4_IDX: ['55', '4b'], - THERMAL_NUM_5_IDX: ['54', '4c'], - } + thermal_sysfspath ={ - THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/55-0048/hwmon/hwmon4/temp1_input"], - THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/55-0049/hwmon/hwmon5/temp1_input"], - THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/55-004a/hwmon/hwmon6/temp1_input"], - THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/55-004b/hwmon/hwmon7/temp1_input"], - THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/54-004c/hwmon/hwmon3/temp1_input"], + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/24-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/25-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/class/hwmon/hwmon1/temp1_input"], } - - #def __init__(self): + def _get_thermal_val(self, thermal_num): if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) return None - device_path = self.get_thermal_to_device_path(thermal_num) - if(os.path.isfile(device_path)): - for filename in glob.glob(device_path): - try: - val_file = open(filename, 'r') - except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) - return None + device_path = self.get_thermal_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None content = val_file.readline().rstrip() if content == '': logging.debug('GET. content is NULL. device_path:%s', device_path) return None try: - val_file.close() + val_file.close() except: logging.debug('GET. unable to close file. device_path:%s', device_path) return None + return int(content) - else: - print "No such device_path=%s"%device_path - return 0 + return 0 def get_num_thermals(self): return self.THERMAL_NUM_MAX - def get_idx_thermal_start(self): - return self.THERMAL_NUM_1_IDX - - def get_size_node_map(self): - return len(self._thermal_to_device_node_mapping) - def get_size_path_map(self): return len(self.thermal_sysfspath) - def get_thermal_to_device_path(self, thermal_num): + def get_thermal_path(self, thermal_num): return self.thermal_sysfspath[thermal_num][0] - def get_thermal_1_val(self): - return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) - - def get_thermal_2_val(self): - return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) - def get_thermal_temp(self): - return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) - def main(): thermal = ThermalUtil() - print "termal1=%d" %thermal._get_thermal_val(1) - print "termal2=%d" %thermal._get_thermal_val(2) - print "termal3=%d" %thermal._get_thermal_val(3) - print "termal4=%d" %thermal._get_thermal_val(4) - print "termal5=%d" %thermal._get_thermal_val(5) - + if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py index eca1eac6b216..6dbf5c2cc720 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py @@ -1,25 +1,22 @@ #!/usr/bin/env python +# -*- coding: utf-8 -* +# Copyright (c) 2019 Edgecore Networks Corporation # -# Copyright (C) 2017 Accton Technology Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # -# This program 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, either version 3 of the License, or -# (at your option) any later version. +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. # -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# # HISTORY: # mm/dd/yyyy (A.D.)# -# 4/20/2018: Jostar modify for as7726_32x -# 12/03/2018:Jostar modify for as7726_32x thermal plan +# 10/24/2019:Jostar create for as4630_54pe thermal plan # ------------------------------------------------------------------ try: @@ -32,11 +29,12 @@ import logging.config import logging.handlers import types - import time # this is only being used as part of the example - import traceback + import time + import traceback + import commands from tabulate import tabulate - from as7726_32x.fanutil import FanUtil - from as7726_32x.thermalutil import ThermalUtil + from as4630_54pe.fanutil import FanUtil + from as4630_54pe.thermalutil import ThermalUtil except ImportError as e: raise ImportError('%s - required module not found' % str(e)) @@ -48,25 +46,20 @@ global log_level -# Air Flow Front to Back : -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system -# One Fan fail : Change Fan speed to 100%(0x0E) -# Air Flow Back to Front : -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message -# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system -# One Fan fail: Change Fan speed to 100%(0x0E) -# sensor_LM75_CPU == sensor_LM75_4B - - + +# Temperature Policy +# If any fan fail , please set fan speed register to 16 +# The max value of fan speed register is 14 +# LM77(48)+LM75(4B)+LM75(4A) > 140, Set 10 +# LM77(48)+LM75(4B)+LM75(4A) > 150, Set 12 +# LM77(48)+LM75(4B)+LM75(4A) > 160, Set 14 +# LM77(48)+LM75(4B)+LM75(4A) < 140, Set 8 +# LM77(48)+LM75(4B)+LM75(4A) < 150, Set 10 +# LM77(48)+LM75(4B)+LM75(4A) < 160, Set 12 +# Reset DUT:LM77(48)>=70C +# class switch(object): def __init__(self, value): self.value = value @@ -87,13 +80,13 @@ def match(self, *args): else: return False - -fan_policy_state=1 +fan_policy_state=0 fan_fail=0 alarm_state = 0 #0->default or clear, 1-->alarm detect test_temp = 0 -test_temp_list = [0, 0, 0, 0, 0, 0] +test_temp_list = [0, 0, 0] temp_test_data=0 +test_temp_revert=0 # Make a class we can use to capture stdout and sterr in the log class device_monitor(object): # static temp var @@ -124,119 +117,71 @@ def __init__(self, log_file, log_level): sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') sys_handler.setLevel(logging.WARNING) logging.getLogger('').addHandler(sys_handler) - - #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) def get_state_from_fan_policy(self, temp, policy): state=0 - - logging.debug('temp=%d', temp) for i in range(0, len(policy)): - #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2]) - if temp > policy[i][2]: - if temp <= policy[i][3]: + if (temp > policy[i][2]): #temp_down + if temp <= policy[i][3]: #temp_up state =i - logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) - logging.debug ('fan_state=%d', state) - break - + return state - def manage_fans(self): - global fan_policy_state global fan_fail global test_temp global test_temp_list global alarm_state - global temp_test_data - - LEVEL_FAN_DEF=0 - LEVEL_FAN_MID=1 - LEVEL_FAN_MAX=2 - LEVEL_TEMP_HIGH=3 - LEVEL_TEMP_CRITICAL=4 - - - fan_policy_f2b = { - LEVEL_FAN_DEF: [38, 0x4, 0, 38000], - LEVEL_FAN_MID: [63, 0x6, 38000, 46000], - LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], - LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], - LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], - } - fan_policy_b2f = { - LEVEL_FAN_DEF: [38, 0x4, 0, 34000], - LEVEL_FAN_MID: [63, 0x8, 34000, 44000], - LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], - LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], - LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], + global temp_test_data + global test_temp_revert + LEVEL_FAN_MIN=0 + LEVEL_FAN_NORMAL=1 + LEVEL_FAN_MID=2 + LEVEL_FAN_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + fan_policy = { + LEVEL_FAN_MIN: [50, 8, 0, 140000], + LEVEL_FAN_NORMAL: [62, 10, 140000, 150000], + LEVEL_FAN_MID: [75, 12, 150000, 160000], + LEVEL_FAN_HIGH: [88, 14, 160000, 240000], + LEVEL_TEMP_CRITICAL: [100, 16, 240000, 300000], } - - fan_policy = fan_policy_f2b - + temp = [0, 0 , 0] + temp_fail=0 thermal = ThermalUtil() fan = FanUtil() - fan_dir=fan.get_fan_dir(1) - if fan_dir == 1: - fan_dri=1 #something wrong, set fan_dir to default val - else: - fan_policy = fan_policy_b2f + ori_duty_cycle=fan.get_fan_duty_cycle() + new_duty_cycle=0 - ori_pwm=fan.get_fan_duty_cycle() - new_pwm=0 - logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) - logging.debug('test_temp=%d', test_temp) - if test_temp==0: - temp1 = thermal._get_thermal_val(1) - temp2 = thermal._get_thermal_val(2) - temp3 = thermal._get_thermal_val(3) - temp4 = thermal._get_thermal_val(4) - temp5 = thermal._get_thermal_val(5) + if test_temp==0: + for i in range(0,3): + temp[i]=thermal._get_thermal_val(i+1) + if temp[i]==0 or temp[i]==None: + temp_fail=1 + logging.warning("Get temp-%d fail", i); + return False else: - temp1 = test_temp_list[0] - temp2 = test_temp_list[1] - temp3 = test_temp_list[2] - temp4 = test_temp_list[3] - temp5 = test_temp_list[4] + if test_temp_revert==0: + temp_test_data=temp_test_data+2000 + else: + temp_test_data=temp_test_data-2000 + + for i in range(0,3): + temp[i]=test_temp_list[i]+temp_test_data fan_fail=0 - - if temp3==0: - temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% - logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') - elif temp4==0: - temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% - logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') - else: - temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 - ori_state=fan_policy_state - - #temp_test_data=temp_test_data+1000 - #temp_get = temp_get + temp_test_data - #print "Unit test:temp_get=%d"%temp_get - - fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) - #print "temp3=%d"%temp3 - #print "temp4=%d"%temp4 - #print "temp_get=%d"%temp_get - - logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5) - logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) - new_pwm = fan_policy[fan_policy_state][0] - if fan_fail==0: - logging.debug('new_fan_cycle=%d', new_pwm) - - if fan_fail==0: - if new_pwm!=ori_pwm: - fan.set_fan_duty_cycle(new_pwm) - logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + temp_val=0 + for i in range(0,3): + if temp[i]==None: + break + temp_val+=temp[i] #Check Fan status for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): if fan.get_fan_status(i)==0: new_pwm=100 - logging.debug('fan_%d fail, set pwm to 100',i) + logging.warning('Fan_%d fail, set pwm to 100',i) if test_temp==0: fan_fail=1 fan.set_fan_duty_cycle(new_pwm) @@ -244,59 +189,38 @@ def manage_fans(self): else: fan_fail=0 - #if fan_policy_state == ori_state: - # return True - #else: - new_state = fan_policy_state + ori_state=fan_policy_state + fan_policy_state=self.get_state_from_fan_policy(temp_val, fan_policy) - #logging.warning('Temperature high alarm testing') - if ori_state==LEVEL_FAN_DEF: - if new_state==LEVEL_TEMP_HIGH: + if fan_policy_state > LEVEL_TEMP_CRITICAL or fan_policy_state < LEVEL_FAN_MIN: + logging.error("Get error fan current_state\n"); + return 0 + + #Decision : Decide new fan pwm percent. + if fan_fail==0 and ori_duty_cycle!=fan_policy[fan_policy_state][0]: + new_duty_cycle = fan_policy[fan_policy_state][0]; + fan.set_fan_duty_cycle(new_duty_cycle) + + if temp[0] >= 70000: #LM75-48 + #critical case*/ + logging.critical('Alarm-Critical for temperature critical is detected, reset DUT') + cmd_str="i2cset -y -f 3 0x60 0x4 0xE4" + time.sleep(2); + status, output = commands.getstatusoutput(cmd_str) + + #logging.debug('ori_state=%d, current_state=%d, temp_val=%d\n\n',ori_state, fan_policy_state, temp_val) + + if ori_state < LEVEL_FAN_HIGH: + if fan_policy_state >= LEVEL_FAN_HIGH: if alarm_state==0: logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected, reboot DUT') - time.sleep(2) - os.system('reboot') - if ori_state==LEVEL_FAN_MID: - if new_state==LEVEL_TEMP_HIGH: - if alarm_state==0: - logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') - if ori_state==LEVEL_FAN_MAX: - if new_state==LEVEL_TEMP_HIGH: - if alarm_state==0: - logging.warning('Alarm for temperature high is detected') - alarm_state=1 - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') + alarm_state=1 + + if fan_policy_state < LEVEL_FAN_MID: if alarm_state==1: - if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm - logging.warning('Alarm for temperature high is cleared') - alarm_state=0 - if ori_state==LEVEL_TEMP_HIGH: - if new_state==LEVEL_TEMP_CRITICAL: - logging.critical('Alarm for temperature critical is detected') - time.sleep(2) - os.system('reboot') - if new_state <= LEVEL_FAN_MID: - logging.warning('Alarm for temperature high is cleared') + logging.info('Alarm for temperature high is cleared') alarm_state=0 - if new_state <= LEVEL_FAN_MAX: - if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm - logging.warning('Alarm for temperature high is cleared') - alarm_state=0 - if ori_state==LEVEL_TEMP_CRITICAL: - if new_state <= LEVEL_FAN_MAX: - logging.warning('Alarm for temperature critical is cleared') - + return True def main(argv): @@ -319,12 +243,12 @@ def main(argv): log_file = arg if sys.argv[1]== '-t': - if len(sys.argv)!=7: - print "temp test, need input six temp" + if len(sys.argv)!=5: + print "temp test, need input three temp" return 0 i=0 - for x in range(2, 7): + for x in range(2, 5): test_temp_list[i]= int(sys.argv[x])*1000 i=i+1 test_temp = 1 @@ -332,14 +256,14 @@ def main(argv): print test_temp_list fan = FanUtil() - fan.set_fan_duty_cycle(38) - print "set default fan speed to 37.5%" + fan.set_fan_duty_cycle(50) + print "set default fan speed to 50%" monitor = device_monitor(log_file, log_level) # Loop forever, doing something useful hopefully: while True: - #monitor.manage_fans() - time.sleep(5) + monitor.manage_fans() + time.sleep(10) #10sec if __name__ == '__main__': main(sys.argv[1:]) - +