diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
old mode 100644
new mode 100755
index 61794979a753..081a83e94ea9
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -21,6 +21,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ACCTON_AS7326_56X_PLATFORM_MODULE) \
$(ACCTON_AS7716_32XB_PLATFORM_MODULE) \
$(ACCTON_AS6712_32X_PLATFORM_MODULE) \
+ $(ACCTON_AS7726_32X_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
old mode 100644
new mode 100755
index 72c2453c5359..d9fbf652c4ed
--- a/platform/broadcom/platform-modules-accton.mk
+++ b/platform/broadcom/platform-modules-accton.mk
@@ -8,6 +8,7 @@ ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION = 1.1
+ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION = 1.1
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION
@@ -17,6 +18,7 @@ export ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION
export ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION
export ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION
export ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION
+export ACCTON_AS7726_32X_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
@@ -52,4 +54,8 @@ ACCTON_AS6712_32X_PLATFORM_MODULE = sonic-platform-accton-as6712-32x_$(ACCTON_AS
$(ACCTON_AS6712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as6712_32x-r0
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS6712_32X_PLATFORM_MODULE)))
+ACCTON_AS7726_32X_PLATFORM_MODULE = sonic-platform-accton-as7726-32x_$(ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION)_amd64.deb
+$(ACCTON_AS7726_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7726_32x-r0
+$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7726_32X_PLATFORM_MODULE)))
+
SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py
new file mode 100755
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py
new file mode 100755
index 000000000000..ca0f3f9da1e3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/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/as7726-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py
new file mode 100755
index 000000000000..96163f1d63ab
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py
@@ -0,0 +1,131 @@
+#!/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_32x
+# 12/03/2018:Jostar modify for as7726_32x thermal plan
+# ------------------------------------------------------------------
+
+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 = 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
+
+ """ 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: ['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"],
+ }
+
+ #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_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)
+#
+# 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/as7726-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile
new file mode 100755
index 000000000000..5b5e6912c56a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile
@@ -0,0 +1,19 @@
+ifneq ($(KERNELRELEASE),)
+obj-m:= accton_as7726_32x_cpld.o accton_as7726_32x_fan.o \
+ accton_as7726_32x_leds.o accton_as7726_32x_psu.o ym2651y.o
+
+else
+ifeq (,$(KERNEL_SRC))
+#$(error KERNEL_SRC is not defined)
+KVERSION=3.16.0-6-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 .tmp_versions Module.markers Module.symvers modules.order
+endif
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c
new file mode 100755
index 000000000000..9ffc3353839c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c
@@ -0,0 +1,919 @@
+/*
+ * 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 as7726_32x 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 {
+ as7726_32x_cpld1,
+ as7726_32x_cpld2,
+ as7726_32x_cpld3
+};
+
+struct as7726_32x_cpld_data {
+ enum cpld_type type;
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+static const struct i2c_device_id as7726_32x_cpld_id[] = {
+ { "as7726_32x_cpld1", as7726_32x_cpld1 },
+ { "as7726_32x_cpld2", as7726_32x_cpld2 },
+ { "as7726_32x_cpld3", as7726_32x_cpld3 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, as7726_32x_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_RESET_ATTR_ID(index) MODULE_RESET_##index
+//#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index
+
+enum as7726_32x_cpld1_sysfs_attributes {
+ CPLD_VERSION,
+ ACCESS,
+ MODULE_PRESENT_ALL,
+ MODULE_RXLOS_ALL,
+ /* 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_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 show_present_all(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_rxlos_all(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 set_reset(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 as7726_32x_cpld_read_internal(struct i2c_client *client, u8 reg);
+static int as7726_32x_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_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, show_status, set_reset, MODULE_RESET_##index)
+#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##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);
+
+
+#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
+
+
+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);
+static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL);
+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_RESET_SENSOR_DEVICE_ATTR(1);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(2);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(3);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(4);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(5);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(6);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(7);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(8);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(9);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(10);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(11);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(12);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(13);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(14);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(15);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(16);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(17);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(18);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(19);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(20);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(21);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(22);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(23);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(24);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(25);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(26);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(27);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(28);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(29);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(30);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(31);
+DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(32);
+
+static struct attribute *as7726_32x_cpld1_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ &sensor_dev_attr_module_present_all.dev_attr.attr,
+ &sensor_dev_attr_module_rx_los_all.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_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(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),
+ 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 as7726_32x_cpld1_group = {
+ .attrs = as7726_32x_cpld1_attributes,
+};
+
+static struct attribute *as7726_32x_cpld2_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group as7726_32x_cpld2_group = {
+ .attrs = as7726_32x_cpld2_attributes,
+};
+
+static struct attribute *as7726_32x_cpld3_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group as7726_32x_cpld3_group = {
+ .attrs = as7726_32x_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[] = {0x30, 0x31, 0x32, 0x33, 0x50};
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7726_32x_cpld_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
+ status = as7726_32x_cpld_read_internal(client, regs[i]);
+
+ if (status < 0) {
+ goto exit;
+ }
+
+ values[i] = ~(u8)status;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ values[4] &= 0x3;
+ return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x\n",
+ values[0], values[1], values[2], values[3], values[4]);
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ u8 value=0;
+ u8 reg = 0x50;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7726_32x_cpld_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ status = as7726_32x_cpld_read_internal(client, reg);
+
+ if (status < 0)
+ goto exit;
+
+ value = (u8)status;
+ value &= 0x0C;
+ value = value >> 2;
+ mutex_unlock(&data->update_lock);
+
+ /* Return values 1 -> 34 in order */
+ return sprintf(buf, "00 00 00 00 %.2x\n", value);
+
+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 as7726_32x_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 = 0x30;
+ mask = 0x1 << (attr->index - MODULE_PRESENT_1);
+ break;
+ case MODULE_PRESENT_9 ... MODULE_PRESENT_16:
+ reg = 0x31;
+ mask = 0x1 << (attr->index - MODULE_PRESENT_9);
+ break;
+ case MODULE_PRESENT_17 ... MODULE_PRESENT_24:
+ reg = 0x32;
+ mask = 0x1 << (attr->index - MODULE_PRESENT_17);
+ break;
+ case MODULE_PRESENT_25 ... MODULE_PRESENT_32:
+ reg = 0x33;
+ mask = 0x1 << (attr->index - MODULE_PRESENT_25);
+ break;
+ case MODULE_PRESENT_33:
+ reg = 0x50;
+ mask = 0x1;
+ break;
+ case MODULE_PRESENT_34:
+ reg = 0x50;
+ mask = 0x2;
+ break;
+ case MODULE_RESET_1 ... MODULE_RESET_8:
+ reg = 0x4;
+ mask = 0x1 << (attr->index - MODULE_RESET_1);
+ break;
+ case MODULE_RESET_9 ... MODULE_RESET_16:
+ reg = 0x5;
+ mask = 0x1 << (attr->index - MODULE_RESET_9);
+ break;
+ case MODULE_RESET_17 ... MODULE_RESET_24:
+ reg = 0x6;
+ mask = 0x1 << (attr->index - MODULE_RESET_17);
+ break;
+ case MODULE_RESET_25 ... MODULE_RESET_32:
+ reg = 0x7;
+ mask = 0x1 << (attr->index - MODULE_RESET_25);
+ break;
+ case MODULE_RXLOS_33:
+ reg = 0x50;
+ mask = 0x4;
+ break;
+ case MODULE_RXLOS_34:
+ reg = 0x50;
+ mask = 0x8;
+ break;
+ case MODULE_TXDISABLE_33:
+ reg = 0x49;
+ mask = 0x1;
+ break;
+ case MODULE_TXDISABLE_34:
+ reg = 0x49;
+ 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 = as7726_32x_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 as7726_32x_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 = 0x49;
+ mask = 0x1;
+ break;
+ case MODULE_TXDISABLE_34:
+ reg = 0x49;
+ mask = 0x2;
+ break;
+ default:
+ return 0;
+ }
+
+ /* Read current status */
+ mutex_lock(&data->update_lock);
+ status = as7726_32x_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+
+ /* Update tx_disable status */
+ if (disable) {
+ status |= mask;
+ }
+ else {
+ status &= ~mask;
+ }
+
+ status = as7726_32x_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 set_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 as7726_32x_cpld_data *data = i2c_get_clientdata(client);
+ long reset;
+ int status;
+ u8 reg = 0, mask = 0;
+
+ status = kstrtol(buf, 10, &reset);
+ if (status) {
+ return status;
+ }
+
+ switch (attr->index)
+ {
+ case MODULE_RESET_1 ... MODULE_RESET_8:
+ reg = 0x4;
+ mask = 0x1 << (attr->index - MODULE_RESET_1);
+ break;
+ case MODULE_RESET_9 ... MODULE_RESET_16:
+ reg = 0x5;
+ mask = 0x1 << (attr->index - MODULE_RESET_9);
+ break;
+ case MODULE_RESET_17 ... MODULE_RESET_24:
+ reg = 0x6;
+ mask = 0x1 << (attr->index - MODULE_RESET_17);
+ break;
+ case MODULE_RESET_25 ... MODULE_RESET_32:
+ reg = 0x7;
+ mask = 0x1 << (attr->index - MODULE_RESET_25);
+ break;
+ default:
+ return 0;
+ }
+
+ /* Read current status */
+ mutex_lock(&data->update_lock);
+ status = as7726_32x_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+
+ /* Update tx_disable status */
+ if (!reset) {
+ status |= mask;
+ }
+ else {
+ status &= ~mask;
+ }
+
+ status = as7726_32x_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 as7726_32x_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 = as7726_32x_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 as7726_32x_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 as7726_32x_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 as7726_32x_cpld_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+ struct as7726_32x_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 as7726_32x_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 as7726_32x_cpld1:
+ group = &as7726_32x_cpld1_group;
+ break;
+ case as7726_32x_cpld2:
+ group = &as7726_32x_cpld2_group;
+ break;
+ case as7726_32x_cpld3:
+ group = &as7726_32x_cpld3_group;
+ break;
+ default:
+ break;
+ }
+
+ if (group) {
+ ret = sysfs_create_group(&client->dev.kobj, group);
+ if (ret) {
+ goto exit_free;
+ }
+ }
+
+ as7726_32x_cpld_add_client(client);
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return ret;
+}
+
+static int as7726_32x_cpld_remove(struct i2c_client *client)
+{
+ struct as7726_32x_cpld_data *data = i2c_get_clientdata(client);
+ const struct attribute_group *group = NULL;
+
+ as7726_32x_cpld_remove_client(client);
+
+ /* Remove sysfs hooks */
+ switch (data->type) {
+ case as7726_32x_cpld1:
+ group = &as7726_32x_cpld1_group;
+ break;
+ case as7726_32x_cpld2:
+ group = &as7726_32x_cpld2_group;
+ break;
+ case as7726_32x_cpld3:
+ group = &as7726_32x_cpld3_group;
+ break;
+ default:
+ break;
+ }
+
+ if (group) {
+ sysfs_remove_group(&client->dev.kobj, group);
+ }
+
+ kfree(data);
+
+ return 0;
+}
+
+static int as7726_32x_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 as7726_32x_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 as7726_32x_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 = as7726_32x_cpld_read_internal(cpld_node->client, reg);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as7726_32x_cpld_read);
+
+int as7726_32x_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 = as7726_32x_cpld_write_internal(cpld_node->client, reg, value);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as7726_32x_cpld_write);
+
+static struct i2c_driver as7726_32x_cpld_driver = {
+ .driver = {
+ .name = "as7726_32x_cpld",
+ .owner = THIS_MODULE,
+ },
+ .probe = as7726_32x_cpld_probe,
+ .remove = as7726_32x_cpld_remove,
+ .id_table = as7726_32x_cpld_id,
+};
+
+static int __init as7726_32x_cpld_init(void)
+{
+ mutex_init(&list_lock);
+ return i2c_add_driver(&as7726_32x_cpld_driver);
+}
+
+static void __exit as7726_32x_cpld_exit(void)
+{
+ i2c_del_driver(&as7726_32x_cpld_driver);
+}
+
+MODULE_AUTHOR("Jostar Yang ");
+MODULE_DESCRIPTION("Accton I2C CPLD driver");
+MODULE_LICENSE("GPL");
+
+module_init(as7726_32x_cpld_init);
+module_exit(as7726_32x_cpld_exit);
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c
new file mode 100755
index 000000000000..beb58804ac94
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c
@@ -0,0 +1,763 @@
+/*
+ * A hwmon driver for the Accton as7726 32x 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 "as7726_32x_fan"
+
+#define NUM_THERMAL_SENSORS (5) /* Get sum of this number of sensors.*/
+#define THERMAL_SENSORS_DRIVER "lm75"
+#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c}
+
+#define IN
+#define OUT
+
+static struct as7726_32x_fan_data *as7726_32x_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 as7726_32x_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 *as7726_32x_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 as7726_32x_fan_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int as7726_32x_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 as7726_32x_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;
+
+ as7726_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */
+ as7726_32x_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,
+ OUT 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 as7726_32x_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 as7726_32x_fan_data *data = as7726_32x_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 as7726_32x_fan_data *data = as7726_32x_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 as7726_32x_fan_group = {
+ .attrs = as7726_32x_fan_attributes,
+};
+
+static struct as7726_32x_fan_data *as7726_32x_fan_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7726_32x_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 as7726_32x_fan update\n");
+ data->valid = 0;
+
+ /* Update fan data
+ */
+ for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
+ int status = as7726_32x_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 as7726_32x_fan_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as7726_32x_fan_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as7726_32x_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, &as7726_32x_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, &as7726_32x_fan_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as7726_32x_fan_remove(struct i2c_client *client)
+{
+ struct as7726_32x_fan_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as7726_32x_fan_group);
+
+ return 0;
+}
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END };
+
+static const struct i2c_device_id as7726_32x_fan_id[] = {
+ { "as7726_32x_fan", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as7726_32x_fan_id);
+
+static struct i2c_driver as7726_32x_fan_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = DRVNAME,
+ },
+ .probe = as7726_32x_fan_probe,
+ .remove = as7726_32x_fan_remove,
+ .id_table = as7726_32x_fan_id,
+ .address_list = normal_i2c,
+};
+
+module_i2c_driver(as7726_32x_fan_driver);
+
+MODULE_AUTHOR("Jostar Yang ");
+MODULE_DESCRIPTION("as7726_32x_fan driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c
new file mode 100755
index 000000000000..65b962e628cc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c
@@ -0,0 +1,438 @@
+/*
+ * A LED driver for the accton_as7726_32x_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 as7726_32x_cpld_read (unsigned short cpld_addr, u8 reg);
+extern int as7726_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+extern void led_classdev_unregister(struct led_classdev *led_cdev);
+extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
+extern void led_classdev_resume(struct led_classdev *led_cdev);
+extern void led_classdev_suspend(struct led_classdev *led_cdev);
+
+#define DRVNAME "accton_as7726_32x_led"
+
+struct accton_as7726_32x_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[1]; /* only 1 register*/
+};
+
+static struct accton_as7726_32x_led_data *ledctl = NULL;
+
+/* LED related data
+ */
+
+#define LED_CNTRLER_I2C_ADDRESS (0x60)
+
+#define LED_TYPE_DIAG_REG_MASK (0x3)
+#define LED_MODE_DIAG_GREEN_VALUE (0x02)
+#define LED_MODE_DIAG_RED_VALUE (0x01)
+#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/
+#define LED_MODE_DIAG_OFF_VALUE (0x03)
+
+
+#define LED_TYPE_LOC_REG_MASK (0x80)
+#define LED_MODE_LOC_ON_VALUE (0)
+#define LED_MODE_LOC_OFF_VALUE (0x80)
+
+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_as7726_32x_led update\n");
+
+ /* Update LED data
+ */
+ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
+ int status = accton_as7726_32x_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_as7726_32x_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_as7726_32x_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_as7726_32x_led_write_value(reg, reg_val);
+
+ /* to prevent the slow-update issue */
+ ledctl->valid = 0;
+
+exit:
+ mutex_unlock(&ledctl->update_lock);
+}
+
+
+static void accton_as7726_32x_led_diag_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG);
+}
+
+static enum led_brightness accton_as7726_32x_led_diag_get(struct led_classdev *cdev)
+{
+ accton_as7726_32x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
+}
+
+static void accton_as7726_32x_led_loc_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC);
+}
+
+static enum led_brightness accton_as7726_32x_led_loc_get(struct led_classdev *cdev)
+{
+ accton_as7726_32x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
+}
+
+static void accton_as7726_32x_led_auto_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+}
+
+static enum led_brightness accton_as7726_32x_led_auto_get(struct led_classdev *cdev)
+{
+ return LED_MODE_AUTO;
+}
+
+static struct led_classdev accton_as7726_32x_leds[] = {
+ [LED_TYPE_DIAG] = {
+ .name = "accton_as7726_32x_led::diag",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7726_32x_led_diag_set,
+ .brightness_get = accton_as7726_32x_led_diag_get,
+ .flags = LED_CORE_SUSPENDRESUME,
+ .max_brightness = LED_MODE_RED,
+ },
+ [LED_TYPE_LOC] = {
+ .name = "accton_as7726_32x_led::loc",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7726_32x_led_loc_set,
+ .brightness_get = accton_as7726_32x_led_loc_get,
+ .flags = LED_CORE_SUSPENDRESUME,
+ .max_brightness = LED_MODE_BLUE,
+ },
+ [LED_TYPE_FAN] = {
+ .name = "accton_as7726_32x_led::fan",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7726_32x_led_auto_set,
+ .brightness_get = accton_as7726_32x_led_auto_get,
+ .flags = LED_CORE_SUSPENDRESUME,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_PSU1] = {
+ .name = "accton_as7726_32x_led::psu1",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7726_32x_led_auto_set,
+ .brightness_get = accton_as7726_32x_led_auto_get,
+ .flags = LED_CORE_SUSPENDRESUME,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_PSU2] = {
+ .name = "accton_as7726_32x_led::psu2",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7726_32x_led_auto_set,
+ .brightness_get = accton_as7726_32x_led_auto_get,
+ .flags = LED_CORE_SUSPENDRESUME,
+ .max_brightness = LED_MODE_AUTO,
+ },
+};
+
+static int accton_as7726_32x_led_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) {
+ led_classdev_suspend(&accton_as7726_32x_leds[i]);
+ }
+
+ return 0;
+}
+
+static int accton_as7726_32x_led_resume(struct platform_device *dev)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) {
+ led_classdev_resume(&accton_as7726_32x_leds[i]);
+ }
+
+ return 0;
+}
+
+static int accton_as7726_32x_led_probe(struct platform_device *pdev)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) {
+ ret = led_classdev_register(&pdev->dev, &accton_as7726_32x_leds[i]);
+
+ if (ret < 0)
+ break;
+ }
+
+ /* Check if all LEDs were successfully registered */
+ if (i != ARRAY_SIZE(accton_as7726_32x_leds)) {
+ int j;
+
+ /* only unregister the LEDs that were successfully registered */
+ for (j = 0; j < i; j++) {
+ led_classdev_unregister(&accton_as7726_32x_leds[i]);
+ }
+ }
+
+ return ret;
+}
+
+static int accton_as7726_32x_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) {
+ led_classdev_unregister(&accton_as7726_32x_leds[i]);
+ }
+
+ return 0;
+}
+
+static struct platform_driver accton_as7726_32x_led_driver = {
+ .probe = accton_as7726_32x_led_probe,
+ .remove = accton_as7726_32x_led_remove,
+ .suspend = accton_as7726_32x_led_suspend,
+ .resume = accton_as7726_32x_led_resume,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init accton_as7726_32x_led_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&accton_as7726_32x_led_driver);
+ if (ret < 0) {
+ goto exit;
+ }
+
+ ledctl = kzalloc(sizeof(struct accton_as7726_32x_led_data), GFP_KERNEL);
+ if (!ledctl) {
+ ret = -ENOMEM;
+ platform_driver_unregister(&accton_as7726_32x_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_as7726_32x_led_driver);
+ kfree(ledctl);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static void __exit accton_as7726_32x_led_exit(void)
+{
+ platform_device_unregister(ledctl->pdev);
+ platform_driver_unregister(&accton_as7726_32x_led_driver);
+ kfree(ledctl);
+}
+
+module_init(accton_as7726_32x_led_init);
+module_exit(accton_as7726_32x_led_exit);
+
+MODULE_AUTHOR("Jostar Yang ");
+MODULE_DESCRIPTION("accton_as7726_32x_led driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c
new file mode 100755
index 000000000000..f4da01e86d9b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c
@@ -0,0 +1,276 @@
+/*
+ * An hwmon driver for accton as7726_32x 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
+
+static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
+static int as7726_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
+extern int as7726_32x_cpld_read(unsigned short cpld_addr, u8 reg);
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END };
+
+/* Each client has this additional data
+ */
+struct as7726_32x_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[9]; /* Model name, read from eeprom */
+};
+
+static struct as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev);
+
+enum as7726_32x_psu_sysfs_attributes {
+ PSU_PRESENT,
+ PSU_MODEL_NAME,
+ PSU_POWER_GOOD
+};
+
+/* 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_model_name,NULL, PSU_MODEL_NAME);
+static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
+
+static struct attribute *as7726_32x_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,
+ 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 as7726_32x_psu_data *data = as7726_32x_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_model_name(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct as7726_32x_psu_data *data = as7726_32x_psu_update_device(dev);
+
+ return sprintf(buf, "%s\n", data->model_name);
+}
+
+static const struct attribute_group as7726_32x_psu_group = {
+ .attrs = as7726_32x_psu_attributes,
+};
+
+static int as7726_32x_psu_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as7726_32x_psu_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as7726_32x_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, &as7726_32x_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, &as7726_32x_psu_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as7726_32x_psu_remove(struct i2c_client *client)
+{
+ struct as7726_32x_psu_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as7726_32x_psu_group);
+ kfree(data);
+
+ return 0;
+}
+
+enum psu_index
+{
+ as7726_32x_psu1,
+ as7726_32x_psu2
+};
+
+static const struct i2c_device_id as7726_32x_psu_id[] = {
+ { "as7726_32x_psu1", as7726_32x_psu1 },
+ { "as7726_32x_psu2", as7726_32x_psu2 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as7726_32x_psu_id);
+
+static struct i2c_driver as7726_32x_psu_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "as7726_32x_psu",
+ },
+ .probe = as7726_32x_psu_probe,
+ .remove = as7726_32x_psu_remove,
+ .id_table = as7726_32x_psu_id,
+ .address_list = normal_i2c,
+};
+
+static int as7726_32x_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 as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7726_32x_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 as7726_32x update\n");
+
+ /* Read psu status */
+ status = as7726_32x_cpld_read(0x60, 0x2);
+
+ 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));
+ power_good = (data->status >> (3-data->index) & 0x1);
+
+ if (power_good) {
+ status = as7726_32x_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';
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+module_i2c_driver(as7726_32x_psu_driver);
+
+MODULE_AUTHOR("Jostar Yang ");
+MODULE_DESCRIPTION("as7726_32x_psu driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c
new file mode 100755
index 000000000000..8e76c56b54fc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c
@@ -0,0 +1,603 @@
+/*
+ * An hwmon driver for the 3Y Power YM-2651Y 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
+
+#define MAX_FAN_DUTY_CYCLE 100
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END };
+
+/* Each client has this additional data
+ */
+struct ym2651y_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 capability; /* Register value */
+ u16 status_word; /* Register value */
+ u8 fan_fault; /* Register value */
+ u8 over_temp; /* Register value */
+ u16 v_out; /* Register value */
+ u16 i_out; /* Register value */
+ u16 p_out; /* Register value */
+ u16 temp; /* Register value */
+ u16 fan_speed; /* Register value */
+ u16 fan_duty_cycle[2]; /* Register value */
+ u8 fan_dir[4]; /* Register value */
+ u8 pmbus_revision; /* Register value */
+ u8 mfr_id[10]; /* Register value */
+ u8 mfr_model[10]; /* Register value */
+ u8 mfr_revsion[3]; /* Register value */
+ u16 mfr_vin_min; /* Register value */
+ u16 mfr_vin_max; /* Register value */
+ u16 mfr_iin_max; /* Register value */
+ u16 mfr_iout_max; /* Register value */
+ u16 mfr_pin_max; /* Register value */
+ u16 mfr_pout_max; /* Register value */
+ u16 mfr_vout_min; /* Register value */
+ u16 mfr_vout_max; /* Register value */
+};
+
+static ssize_t show_byte(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_word(struct device *dev, struct device_attribute *da,
+ char *buf);
+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_over_temp(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
+ char *buf);
+static struct ym2651y_data *ym2651y_update_device(struct device *dev);
+static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value);
+
+enum ym2651y_sysfs_attributes {
+ PSU_POWER_ON = 0,
+ PSU_TEMP_FAULT,
+ PSU_POWER_GOOD,
+ PSU_FAN1_FAULT,
+ PSU_FAN_DIRECTION,
+ PSU_OVER_TEMP,
+ PSU_V_OUT,
+ PSU_I_OUT,
+ PSU_P_OUT,
+ PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/
+ PSU_TEMP1_INPUT,
+ PSU_FAN1_SPEED,
+ PSU_FAN1_DUTY_CYCLE,
+ PSU_PMBUS_REVISION,
+ PSU_MFR_ID,
+ PSU_MFR_MODEL,
+ PSU_MFR_REVISION,
+ PSU_MFR_VIN_MIN,
+ PSU_MFR_VIN_MAX,
+ PSU_MFR_VOUT_MIN,
+ PSU_MFR_VOUT_MAX,
+ PSU_MFR_IIN_MAX,
+ PSU_MFR_IOUT_MAX,
+ PSU_MFR_PIN_MAX,
+ PSU_MFR_POUT_MAX
+};
+
+/* sysfs attributes for hwmon
+ */
+static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON);
+static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
+static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
+static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT);
+static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
+static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT);
+static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT);
+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_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
+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_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION);
+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_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
+static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
+static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
+
+/*Duplicate nodes for lm-sensors.*/
+static SENSOR_DEVICE_ATTR(power1_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 *ym2651y_attributes[] = {
+ &sensor_dev_attr_psu_power_on.dev_attr.attr,
+ &sensor_dev_attr_psu_temp_fault.dev_attr.attr,
+ &sensor_dev_attr_psu_power_good.dev_attr.attr,
+ &sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
+ &sensor_dev_attr_psu_over_temp.dev_attr.attr,
+ &sensor_dev_attr_psu_v_out.dev_attr.attr,
+ &sensor_dev_attr_psu_i_out.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_speed_rpm.dev_attr.attr,
+ &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
+ &sensor_dev_attr_psu_fan_dir.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_vin_min.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr,
+ /*Duplicate nodes for lm-sensors.*/
+ &sensor_dev_attr_power1_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 ssize_t show_byte(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) :
+ sprintf(buf, "0\n");
+}
+
+static ssize_t show_word(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+ u16 status = 0;
+
+ switch (attr->index) {
+ case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */
+ status = (data->status_word & 0x40) ? 0 : 1;
+ break;
+ case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */
+ status = (data->status_word & 0x4) >> 2;
+ break;
+ case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */
+ status = (data->status_word & 0x800) ? 0 : 1;
+ break;
+ }
+
+ return sprintf(buf, "%d\n", status);
+}
+
+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 ym2651y_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;
+ ym2651y_write_word(client, 0x3B + 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 ym2651y_data *data = ym2651y_update_device(dev);
+
+ u16 value = 0;
+ int exponent, mantissa;
+ int multiplier = 1000;
+
+ switch (attr->index) {
+ case PSU_V_OUT:
+ value = data->v_out;
+ break;
+ case PSU_I_OUT:
+ value = data->i_out;
+ break;
+ case PSU_P_OUT_UV:
+ multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/
+ /*Passing through*/
+ case PSU_P_OUT:
+ value = data->p_out;
+ break;
+ case PSU_TEMP1_INPUT:
+ value = data->temp;
+ break;
+ case PSU_FAN1_SPEED:
+ value = data->fan_speed;
+ multiplier = 1;
+ break;
+ case PSU_FAN1_DUTY_CYCLE:
+ value = data->fan_duty_cycle[0];
+ multiplier = 1;
+ break;
+ case PSU_MFR_VIN_MIN:
+ value = data->mfr_vin_min;
+ break;
+ case PSU_MFR_VIN_MAX:
+ value = data->mfr_vin_max;
+ break;
+ case PSU_MFR_VOUT_MIN:
+ value = data->mfr_vout_min;
+ break;
+ case PSU_MFR_VOUT_MAX:
+ value = data->mfr_vout_max;
+ break;
+ case PSU_MFR_PIN_MAX:
+ value = data->mfr_pin_max;
+ break;
+ case PSU_MFR_POUT_MAX:
+ value = data->mfr_pout_max;
+ break;
+ case PSU_MFR_IOUT_MAX:
+ value = data->mfr_iout_max;
+ break;
+ case PSU_MFR_IIN_MAX:
+ value = data->mfr_iin_max;
+ break;
+ }
+
+ exponent = two_complement_to_int(value >> 11, 5, 0x1f);
+ mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
+ 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 ym2651y_data *data = ym2651y_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_over_temp(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->over_temp >> 7);
+}
+
+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 ym2651y_data *data = ym2651y_update_device(dev);
+ u8 *ptr = NULL;
+
+ switch (attr->index) {
+ case PSU_FAN_DIRECTION: /* psu_fan_dir */
+ ptr = data->fan_dir;
+ break;
+ case PSU_MFR_ID: /* psu_mfr_id */
+ ptr = data->mfr_id;
+ break;
+ case PSU_MFR_MODEL: /* psu_mfr_model */
+ ptr = data->mfr_model;
+ break;
+ case PSU_MFR_REVISION: /* psu_mfr_revision */
+ ptr = data->mfr_revsion;
+ break;
+ default:
+ return 0;
+ }
+
+ return sprintf(buf, "%s\n", ptr);
+}
+
+static const struct attribute_group ym2651y_group = {
+ .attrs = ym2651y_attributes,
+};
+
+static int ym2651y_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct ym2651y_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL);
+ if (!data) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ dev_info(&client->dev, "chip found\n");
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &ym2651y_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, &ym2651y_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int ym2651y_remove(struct i2c_client *client)
+{
+ struct ym2651y_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
+ kfree(data);
+
+ return 0;
+}
+
+static const struct i2c_device_id ym2651y_id[] = {
+ { "ym2651", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ym2651y_id);
+
+static struct i2c_driver ym2651y_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "ym2651",
+ },
+ .probe = ym2651y_probe,
+ .remove = ym2651y_remove,
+ .id_table = ym2651y_id,
+ .address_list = normal_i2c,
+};
+
+static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int ym2651y_read_word(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_word_data(client, reg);
+}
+
+static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
+{
+ return i2c_smbus_write_word_data(client, reg, value);
+}
+
+static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data,
+ int data_len)
+{
+ int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
+
+ if (unlikely(result < 0))
+ goto abort;
+ if (unlikely(result != data_len)) {
+ result = -EIO;
+ goto abort;
+ }
+
+ result = 0;
+
+abort:
+ return result;
+}
+
+struct reg_data_byte {
+ u8 reg;
+ u8 *value;
+};
+
+struct reg_data_word {
+ u8 reg;
+ u16 *value;
+};
+
+static struct ym2651y_data *ym2651y_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ym2651y_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;
+ u8 fan_dir[5] = {0};
+ struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
+ {0x7d, &data->over_temp},
+ {0x81, &data->fan_fault},
+ {0x98, &data->pmbus_revision}};
+ struct reg_data_word regs_word[] = { {0x79, &data->status_word},
+ {0x8b, &data->v_out},
+ {0x8c, &data->i_out},
+ {0x96, &data->p_out},
+ {0x8d, &data->temp},
+ {0x3b, &(data->fan_duty_cycle[0])},
+ {0x3c, &(data->fan_duty_cycle[1])},
+ {0x90, &data->fan_speed},
+ {0xa0, &data->mfr_vin_min},
+ {0xa1, &data->mfr_vin_max},
+ {0xa2, &data->mfr_iin_max},
+ {0xa3, &data->mfr_pin_max},
+ {0xa4, &data->mfr_vout_min},
+ {0xa5, &data->mfr_vout_max},
+ {0xa6, &data->mfr_iout_max},
+ {0xa7, &data->mfr_pout_max}};
+
+ dev_dbg(&client->dev, "Starting ym2651 update\n");
+
+ /* Read byte data */
+ for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
+ status = ym2651y_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 = ym2651y_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 fan_direction */
+ command = 0xC3;
+ status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1);
+
+ if (status < 0) {
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+ }
+
+ strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1);
+ data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0';
+
+ /* Read mfr_id */
+ command = 0x99;
+ status = ym2651y_read_block(client, command, data->mfr_id,
+ ARRAY_SIZE(data->mfr_id)-1);
+ data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ /* Read mfr_model */
+ command = 0x9a;
+ status = ym2651y_read_block(client, command, data->mfr_model,
+ ARRAY_SIZE(data->mfr_model)-1);
+ data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ /* Read mfr_revsion */
+ command = 0x9b;
+ status = ym2651y_read_block(client, command, data->mfr_revsion,
+ ARRAY_SIZE(data->mfr_revsion)-1);
+ data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+module_i2c_driver(ym2651y_driver);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("3Y Power YM-2651Y driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service
new file mode 100755
index 000000000000..d29342a56fe1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Accton AS7726-32X Platform MAC hnadle service
+Before=pmon.service
+After=sysinit.target
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/accton_handle_idt.sh
+KillSignal=SIGKILL
+SuccessExitStatus=SIGKILL
+
+# Resource Limitations
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service
new file mode 100755
index 000000000000..e18d592d6c19
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Accton AS7726-32X Platform Monitoring FAN service
+Before=pmon.service
+After=sysinit.target
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/accton_as7726_32x_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/as7726-32x/service/as7726-32x-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service
new file mode 100755
index 000000000000..99f7479494e0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Accton AS7726-32X Platform Monitoring PSU service
+Before=pmon.service
+After=sysinit.target
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/accton_as7726_32x_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/as7726-32x/service/as7726-32x-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service
new file mode 100755
index 000000000000..5b04ad410101
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Accton AS7726-32X Platform Monitoring service
+Before=pmon.service
+After=as7726-32x-platform-handle_mac.service
+DefaultDependencies=no
+
+[Service]
+ExecStartPre=/usr/local/bin/accton_as7726_32x_util.py install
+ExecStart=/usr/local/bin/accton_as7726_32x_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/as7726-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py
new file mode 100755
index 000000000000..9841874dbd1e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from setuptools import setup
+os.listdir
+
+setup(
+ name='as7726_32x',
+ version='1.0',
+ description='Module to initialize Accton AS7726-32X platforms',
+
+ packages=['as7726_32x'],
+ package_dir={'as7726_32x': 'as7726-32x/classes'},
+)
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README
new file mode 100755
index 000000000000..44e03cab5f52
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/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/as7726-32x/utils/accton_as7726_32x_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py
new file mode 100755
index 000000000000..b88b440c9032
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py
@@ -0,0 +1,345 @@
+#!/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.)#
+# 4/20/2018: Jostar modify for as7726_32x
+# 12/03/2018:Jostar modify for as7726_32x 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 as7726_32x.fanutil import FanUtil
+ from as7726_32x.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_as7726_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/as7726-32x/utils/accton_as7726_32x_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py
new file mode 100755
index 000000000000..de737b99f1f3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_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.)
+# 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_as7726_32x_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, 2] #init state=2, insert=1, remove=0
+fan_status_state=[2, 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/54-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/as7726-32x/utils/accton_as7726_32x_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py
new file mode 100755
index 000000000000..618c58eec872
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_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.)
+# 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_as7726_32x_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: "50-0053",
+ 1: "49-0050",
+ }
+
+ """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/as7726-32x/utils/accton_as7726_32x_util.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py
new file mode 100755
index 000000000000..89643edd621a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py
@@ -0,0 +1,572 @@
+#!/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 = 'as7726_32x'
+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':54}
+
+
+led_prefix ='/sys/devices/platform/as7716_32x_led/leds/accton_'+PROJECT_NAME+'_led::'
+fan_prefix ='/sys/devices/platform/as7716_32x_'
+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': ['fan4_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'],
+ }
+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': ['54-004c', '55-0048','55-0049', '55-004a', '55-004b'] ,
+ 'psu': ['49-0050','50-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 = [21, 22, 23, 24, 26, 25, 28, 27,
+ 17, 18, 19, 20, 29, 30, 31, 32,
+ 33, 34, 35, 36, 45, 46, 47, 48,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 15, 16]
+
+mknod =[
+'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device',
+'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device',
+
+'echo as7726_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-11/new_device',
+'echo as7726_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-12/new_device',
+'echo as7726_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-13/new_device',
+
+'echo as7726_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-54/new_device',
+
+
+'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-54/new_device',
+'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-55/new_device',
+'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-55/new_device',
+'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-55/new_device',
+'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-55/new_device',
+
+
+# PSU-1
+'echo as7726_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-50/new_device',
+'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-50/new_device',
+
+# PSU-2
+'echo as7726_32x_psu2 0x50> /sys/bus/i2c/devices/i2c-49/new_device',
+'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-49/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]) ==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 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
+
+def cpld_reset_mac():
+ ret, lsmod = log_os_system("i2cset -y 0 0x77 0x1", 0)
+ ret, lsmod = log_os_system("i2cset -y 0 0x76 0x4", 0)
+ ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0x77", 0)
+ time.sleep(1)
+ ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0xf7", 0)
+ return True
+
+
+
+#'modprobe cpr_4011_4mxx',
+
+kos = [
+'depmod -ae',
+'modprobe i2c_dev',
+'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
+'modprobe ym2651y',
+'modprobe accton_as7726_32x_cpld',
+'modprobe accton_as7726_32x_fan',
+'modprobe accton_as7726_32x_leds',
+'modprobe accton_as7726_32x_psu',
+'modprobe optoe']
+
+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
+
+ #status=cpld_reset_mac()
+ 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)
+
+ 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')
+ # 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)
+ 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/as7726-32x/utils/accton_handle_idt.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh
new file mode 100755
index 000000000000..b43f475eff04
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ -s /usr/local/bin/done_idt_init ];then
+ echo "There is a done_idt_init file"
+else
+
+ cat /etc/init.d/opennsl-modules-3.16.0-5-amd64|grep mac_handle.sh
+ if [ $? -ne 0 ];then
+ echo "Add idt_init.sh to opennsl-modules for TD3 MAC"
+ sed -i '/modprobe linux-kernel-bde/i sleep 1' /etc/init.d/opennsl-modules-3.16.0-5-amd64
+ sed -i '/sleep/i /usr/local/bin/idt_init.sh' /etc/init.d/opennsl-modules-3.16.0-5-amd64
+ sed -i '/idt_init/i echo "IDT init" ' /etc/init.d/opennsl-modules-3.16.0-5-amd64
+ sed -i '/IDT init/i echo 1 > /usr/local/bin/done_idt_init' /etc/init.d/opennsl-modules-3.16.0-5-amd64
+
+ fi
+
+fi
+
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh
new file mode 100755
index 000000000000..257a0242702f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh
@@ -0,0 +1,152 @@
+#!/bin/bash
+test_log=/usr/local/bin/check_idt_status.txt
+modprobe i2c-i801
+modprobe i2c-dev
+i2cset -y 0 0x77 0x1
+i2cset -y 0 0x76 0x1
+i2cget -y 0 0x54 0 b > /dev/null
+if [ $? -ne 0 ];then
+ printf "Device 8v89307(0x54) not found\n"
+ exit 1
+fi
+echo "IDT 82V89307 "
+echo "idt init 1"
+# Title = --- IDT 82V89307 Registers ---
+#Select to Page 0
+i2cset -y 0 0x54 0x2D 0x00
+i2cset -y 0 0x54 0x7F 0x05
+i2cset -y 0 0x54 0x7E 0x85
+i2cset -y 0 0x54 0x7B 0x00
+i2cset -y 0 0x54 0x7A 0x00
+i2cset -y 0 0x54 0x79 0x40
+i2cset -y 0 0x54 0x78 0x06
+i2cset -y 0 0x54 0x73 0x40
+i2cset -y 0 0x54 0x72 0x40
+
+# OUT3:25MHz
+i2cset -y 0 0x54 0x71 0x0A
+i2cset -y 0 0x54 0x70 0x00
+
+# OUT1:1pps
+i2cset -y 0 0x54 0x6B 0x4E
+i2cset -y 0 0x54 0x69 0x00
+i2cset -y 0 0x54 0x68 0x00
+i2cset -y 0 0x54 0x67 0x19
+i2cset -y 0 0x54 0x66 0xAB
+i2cset -y 0 0x54 0x65 0x8C
+i2cset -y 0 0x54 0x64 0x00
+i2cset -y 0 0x54 0x63 0x00
+i2cset -y 0 0x54 0x62 0x00
+i2cset -y 0 0x54 0x5F 0x00
+i2cset -y 0 0x54 0x5E 0x00
+i2cset -y 0 0x54 0x5D 0x00
+i2cset -y 0 0x54 0x5C 0x78
+i2cset -y 0 0x54 0x5B 0x02
+i2cset -y 0 0x54 0x5A 0xE5
+i2cset -y 0 0x54 0x59 0x88
+i2cset -y 0 0x54 0x58 0x4B
+i2cset -y 0 0x54 0x57 0x6C
+i2cset -y 0 0x54 0x56 0x6C
+
+# Lock to DPLL, output 625MHz
+i2cset -y 0 0x54 0x55 0x80
+i2cset -y 0 0x54 0x53 0x00
+i2cset -y 0 0x54 0x52 0x81
+i2cset -y 0 0x54 0x50 0x00
+i2cset -y 0 0x54 0x4F 0x00
+i2cset -y 0 0x54 0x4E 0x00
+i2cset -y 0 0x54 0x4C 0xCB
+i2cset -y 0 0x54 0x4A 0x00
+i2cset -y 0 0x54 0x45 0x66
+i2cset -y 0 0x54 0x44 0x66
+i2cset -y 0 0x54 0x42 0x80
+i2cset -y 0 0x54 0x41 0x03
+i2cset -y 0 0x54 0x40 0x01
+i2cset -y 0 0x54 0x3F 0x08
+i2cset -y 0 0x54 0x3E 0x04
+i2cset -y 0 0x54 0x3D 0x20
+i2cset -y 0 0x54 0x3C 0x13
+i2cset -y 0 0x54 0x3B 0x00
+i2cset -y 0 0x54 0x3A 0x98
+i2cset -y 0 0x54 0x39 0x01
+i2cset -y 0 0x54 0x38 0xE6
+i2cset -y 0 0x54 0x37 0x04
+i2cset -y 0 0x54 0x36 0xCE
+i2cset -y 0 0x54 0x35 0x7C
+i2cset -y 0 0x54 0x34 0x01
+i2cset -y 0 0x54 0x33 0x08
+i2cset -y 0 0x54 0x32 0x08
+i2cset -y 0 0x54 0x31 0x08
+i2cset -y 0 0x54 0x30 0x03
+i2cset -y 0 0x54 0x2F 0x23
+i2cset -y 0 0x54 0x2E 0x0B
+i2cset -y 0 0x54 0x2D 0x00
+i2cset -y 0 0x54 0x28 0x76
+i2cset -y 0 0x54 0x27 0x54
+i2cset -y 0 0x54 0x25 0x00
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x23 0x06
+i2cset -y 0 0x54 0x1A 0x8C
+i2cset -y 0 0x54 0x19 0x8C
+i2cset -y 0 0x54 0x18 0x00
+i2cset -y 0 0x54 0x16 0x0D
+i2cset -y 0 0x54 0x11 0x00
+i2cset -y 0 0x54 0x10 0x00
+i2cset -y 0 0x54 0x0E 0x3F
+i2cset -y 0 0x54 0x0D 0xFF
+i2cset -y 0 0x54 0x0C 0x02
+i2cset -y 0 0x54 0x0B 0xA1
+i2cset -y 0 0x54 0x0A 0x89
+i2cset -y 0 0x54 0x09 0xA2
+i2cset -y 0 0x54 0x08 0x32
+i2cset -y 0 0x54 0x06 0x00
+i2cset -y 0 0x54 0x05 0x00
+i2cset -y 0 0x54 0x04 0x00
+i2cset -y 0 0x54 0x03 0x00
+i2cset -y 0 0x54 0x02 0x05
+i2cset -y 0 0x54 0x01 0x33
+i2cset -y 0 0x54 0x00 0x91
+
+echo "idt init 2"
+# PreDivider_Parameters
+#IN1
+i2cset -y 0 0x54 0x23 0x05
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x25 0x00
+#IN2
+i2cset -y 0 0x54 0x23 0x06
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x25 0x00
+#IN3
+i2cset -y 0 0x54 0x23 0x03
+i2cset -y 0 0x54 0x24 0x00
+i2cset -y 0 0x54 0x25 0x00
+
+echo "idt init 3"
+# Page1_Parameters
+#Select to Page 1
+i2cset -y 0 0x54 0x2D 0x01
+i2cset -y 0 0x54 0x30 0x03
+i2cset -y 0 0x54 0x31 0x08
+i2cset -y 0 0x54 0x32 0x08
+i2cset -y 0 0x54 0x33 0x08
+i2cset -y 0 0x54 0x35 0x7C
+i2cset -y 0 0x54 0x36 0xCE
+i2cset -y 0 0x54 0x37 0x04
+i2cset -y 0 0x54 0x38 0xE6
+i2cset -y 0 0x54 0x39 0x01
+i2cset -y 0 0x54 0x3A 0x98
+i2cset -y 0 0x54 0x3B 0x00
+i2cset -y 0 0x54 0x3C 0x13
+i2cset -y 0 0x54 0x3D 0x20
+#Return to Page 0
+i2cset -y 0 0x54 0x2D 0x00
+
+echo "idt init 4"
+#reset the in-path mux
+i2cset -y 0 0x76 0x0
+i2cset -y 0 0x77 0x0
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh
new file mode 100755
index 000000000000..9f688058c305
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh
@@ -0,0 +1,242 @@
+#!/bin/bash
+test_log=/usr/local/bin/check_mac_status.txt
+modprobe i2c-i801
+modprobe i2c-dev
+i2cset -y 0 0x77 0x1
+i2cset -y 0 0x76 0x1
+i2cget -y 0 0x54 0 b > /dev/null
+if [ $? -ne 0 ];then
+ printf "Device 8v89307(0x54) not found\n"
+ i2cdetect -y 0
+ echo "Reset both MAC and PCI (write 0x6F)"
+ i2cset -y 0 0x60 0x8 0x6f
+
+ echo "Sleep 1s"
+ sleep 1
+
+ echo "Pull back MAC reset, keep PCIE reset (write 0xEF)"
+ i2cset -y 0 0x60 0x7 0xef
+
+ echo "Sleep 1s"
+ sleep 1
+
+ echo "Set to default normal state (write 0xFF)"
+ i2cset -y 0 0x60 0x8 0xff
+
+
+ echo "remove PCI device"
+ echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove
+ ls /sys/bus/pci/devices/
+ echo "rescan PCI device"
+ echo 1 > /sys/bus/pci/rescan
+ ls /sys/bus/pci/devices/
+ echo "Sleep 1s"
+ sleep 1
+ lspci -n|grep 07:00.0
+ if [ $? -ne 0 ];then
+ echo "Broadcom Corporation Device is not detect">>$test_log
+ echo "rescan PCI again" >>$test_log
+ echo 1 > /sys/bus/pci/rescan
+ sleep 1
+ lspci -n|grep 07:00.0
+ if [ $? -ne 0 ];then
+ echo "Broadcom Corporation Device NG">>$test_log
+ echo "rescan PCI again-2" >>$test_log
+ echo 1 > /sys/bus/pci/rescan
+ sleep 1
+ else
+ echo "done mac_pci_reset_rescan"
+ fi
+ fi
+
+ exit 1
+fi
+echo "idt init 1"
+# Title = --- IDT 82V89307 Registers ---
+#Select to Page 0
+i2cset -y 0 0x54 0x2D 0x00
+i2cset -y 0 0x54 0x7F 0x05
+i2cset -y 0 0x54 0x7E 0x85
+i2cset -y 0 0x54 0x7B 0x00
+i2cset -y 0 0x54 0x7A 0x00
+i2cset -y 0 0x54 0x79 0x40
+i2cset -y 0 0x54 0x78 0x06
+i2cset -y 0 0x54 0x73 0x40
+i2cset -y 0 0x54 0x72 0x40
+
+# OUT3:25MHz
+i2cset -y 0 0x54 0x71 0x0A
+i2cset -y 0 0x54 0x70 0x00
+
+# OUT1:1pps
+i2cset -y 0 0x54 0x6B 0x4E
+i2cset -y 0 0x54 0x69 0x00
+i2cset -y 0 0x54 0x68 0x00
+i2cset -y 0 0x54 0x67 0x19
+i2cset -y 0 0x54 0x66 0xAB
+i2cset -y 0 0x54 0x65 0x8C
+i2cset -y 0 0x54 0x64 0x00
+i2cset -y 0 0x54 0x63 0x00
+i2cset -y 0 0x54 0x62 0x00
+i2cset -y 0 0x54 0x5F 0x00
+i2cset -y 0 0x54 0x5E 0x00
+i2cset -y 0 0x54 0x5D 0x00
+i2cset -y 0 0x54 0x5C 0x78
+i2cset -y 0 0x54 0x5B 0x02
+i2cset -y 0 0x54 0x5A 0xE5
+i2cset -y 0 0x54 0x59 0x88
+i2cset -y 0 0x54 0x58 0x4B
+i2cset -y 0 0x54 0x57 0x6C
+i2cset -y 0 0x54 0x56 0x6C
+
+# Lock to DPLL, output 625MHz
+i2cset -y 0 0x54 0x55 0x80
+i2cset -y 0 0x54 0x53 0x00
+i2cset -y 0 0x54 0x52 0x81
+i2cset -y 0 0x54 0x50 0x00
+i2cset -y 0 0x54 0x4F 0x00
+i2cset -y 0 0x54 0x4E 0x00
+i2cset -y 0 0x54 0x4C 0xCB
+i2cset -y 0 0x54 0x4A 0x00
+i2cset -y 0 0x54 0x45 0x66
+i2cset -y 0 0x54 0x44 0x66
+i2cset -y 0 0x54 0x42 0x80
+i2cset -y 0 0x54 0x41 0x03
+i2cset -y 0 0x54 0x40 0x01
+i2cset -y 0 0x54 0x3F 0x08
+i2cset -y 0 0x54 0x3E 0x04
+i2cset -y 0 0x54 0x3D 0x20
+i2cset -y 0 0x54 0x3C 0x13
+i2cset -y 0 0x54 0x3B 0x00
+i2cset -y 0 0x54 0x3A 0x98
+i2cset -y 0 0x54 0x39 0x01
+i2cset -y 0 0x54 0x38 0xE6
+i2cset -y 0 0x54 0x37 0x04
+i2cset -y 0 0x54 0x36 0xCE
+i2cset -y 0 0x54 0x35 0x7C
+i2cset -y 0 0x54 0x34 0x01
+i2cset -y 0 0x54 0x33 0x08
+i2cset -y 0 0x54 0x32 0x08
+i2cset -y 0 0x54 0x31 0x08
+i2cset -y 0 0x54 0x30 0x03
+i2cset -y 0 0x54 0x2F 0x23
+i2cset -y 0 0x54 0x2E 0x0B
+i2cset -y 0 0x54 0x2D 0x00
+i2cset -y 0 0x54 0x28 0x76
+i2cset -y 0 0x54 0x27 0x54
+i2cset -y 0 0x54 0x25 0x00
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x23 0x06
+i2cset -y 0 0x54 0x1A 0x8C
+i2cset -y 0 0x54 0x19 0x8C
+i2cset -y 0 0x54 0x18 0x00
+i2cset -y 0 0x54 0x16 0x0D
+i2cset -y 0 0x54 0x11 0x00
+i2cset -y 0 0x54 0x10 0x00
+i2cset -y 0 0x54 0x0E 0x3F
+i2cset -y 0 0x54 0x0D 0xFF
+i2cset -y 0 0x54 0x0C 0x02
+i2cset -y 0 0x54 0x0B 0xA1
+i2cset -y 0 0x54 0x0A 0x89
+i2cset -y 0 0x54 0x09 0xA2
+i2cset -y 0 0x54 0x08 0x32
+i2cset -y 0 0x54 0x06 0x00
+i2cset -y 0 0x54 0x05 0x00
+i2cset -y 0 0x54 0x04 0x00
+i2cset -y 0 0x54 0x03 0x00
+i2cset -y 0 0x54 0x02 0x05
+i2cset -y 0 0x54 0x01 0x33
+i2cset -y 0 0x54 0x00 0x91
+
+echo "idt init 2"
+# PreDivider_Parameters
+#IN1
+i2cset -y 0 0x54 0x23 0x05
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x25 0x00
+#IN2
+i2cset -y 0 0x54 0x23 0x06
+i2cset -y 0 0x54 0x24 0x03
+i2cset -y 0 0x54 0x25 0x00
+#IN3
+i2cset -y 0 0x54 0x23 0x03
+i2cset -y 0 0x54 0x24 0x00
+i2cset -y 0 0x54 0x25 0x00
+
+echo "idt init 3"
+# Page1_Parameters
+#Select to Page 1
+i2cset -y 0 0x54 0x2D 0x01
+i2cset -y 0 0x54 0x30 0x03
+i2cset -y 0 0x54 0x31 0x08
+i2cset -y 0 0x54 0x32 0x08
+i2cset -y 0 0x54 0x33 0x08
+i2cset -y 0 0x54 0x35 0x7C
+i2cset -y 0 0x54 0x36 0xCE
+i2cset -y 0 0x54 0x37 0x04
+i2cset -y 0 0x54 0x38 0xE6
+i2cset -y 0 0x54 0x39 0x01
+i2cset -y 0 0x54 0x3A 0x98
+i2cset -y 0 0x54 0x3B 0x00
+i2cset -y 0 0x54 0x3C 0x13
+i2cset -y 0 0x54 0x3D 0x20
+#Return to Page 0
+i2cset -y 0 0x54 0x2D 0x00
+
+echo "idt init 4"
+#reset the in-path mux
+i2cset -y 0 0x76 0x0
+i2cset -y 0 0x77 0x0
+
+#flip MAC reset at CPLD
+echo "Work around: We need to reset MAC after set 8v89307 clock output"
+echo " or it is possible to get sdk init failure sometimes"
+echo "MAC reset at CPLD"
+i2cset -y 0 0x77 0x1
+i2cset -y 0 0x76 0x4
+#i2cset -y 0 0x60 0x8 0x7f
+#sleep 1
+#i2cset -y 0 0x60 0x8 0xff
+
+ echo "Reset both MAC and PCI (write 0x6F)"
+ i2cset -y 0 0x60 0x8 0x6f
+
+ echo "Sleep 1s"
+ sleep 1
+
+ echo "Pull back MAC reset, keep PCIE reset (write 0xEF)"
+ i2cset -y 0 0x60 0x7 0xef
+
+ echo "Sleep 1s"
+ sleep 1
+
+ echo "Set to default normal state (write 0xFF)"
+ i2cset -y 0 0x60 0x8 0xff
+
+
+ echo "remove PCI device"
+ echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove
+ ls /sys/bus/pci/devices/
+ echo "rescan PCI device"
+ echo 1 > /sys/bus/pci/rescan
+ ls /sys/bus/pci/devices/
+ echo "Sleep 1s"
+ sleep 1
+ lspci -n|grep 07:00.0
+ if [ $? -ne 0 ];then
+ echo "Broadcom Corporation Device is not detect">>$test_log
+ echo "rescan PCI again" >>$test_log
+ echo 1 > /sys/bus/pci/rescan
+ sleep 1
+ lspci -n|grep 07:00.0
+ if [ $? -ne 0 ];then
+ echo "Broadcom Corporation Device NG">>$test_log
+ echo "rescan PCI again-2" >>$test_log
+ echo 1 > /sys/bus/pci/rescan
+ sleep 1
+ else
+ echo "done mac_pci_reset_rescan"
+ fi
+ fi
+
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control
index c2e4ccc795df..e8db57c6a155 100755
--- a/platform/broadcom/sonic-platform-modules-accton/debian/control
+++ b/platform/broadcom/sonic-platform-modules-accton/debian/control
@@ -36,3 +36,8 @@ Description: kernel modules for platform devices such as fan, led, sfp
Package: sonic-platform-accton-as6712-32x
Architecture: amd64
Description: kernel modules for platform devices such as fan, led, sfp
+
+Package: sonic-platform-accton-as7726-32x
+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 2ac628b45cb3..7f1b9bfdce9e 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
+MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service