From 1c32321805e4f8f0693a7a7d79da350a5002ae4a Mon Sep 17 00:00:00 2001
From: simonJi2018 <37395146+simonJi2018@users.noreply.github.com>
Date: Mon, 2 Apr 2018 19:06:00 -0700
Subject: [PATCH] [device]: Add a new supported device accton-as7116 (#1539)
* Upgrade SAI to v1.2.4
* Add a new supported device accton as7116
* Add maintainer info for deb
---
.../Accton-AS7116-54X/port_config.ini | 58 +
.../Accton-AS7116-54X/port_config_as7116.ini | 55 +
.../Accton-AS7116-54X/sai.profile | 2 +
.../installer.conf | 3 +
.../led_proc_init.nps | 20 +
.../x86_64-accton_as7116_54x-r0/minigraph.xml | 1074 +++++++++++++
.../plugins/eeprom.py | 21 +
.../plugins/sfputil.py | 155 ++
platform/nephos/one-image.mk | 3 +-
platform/nephos/rules.mk | 1 +
.../sonic-platform-modules-accton/LICENSE | 16 +
.../sonic-platform-modules-accton/README.md | 1 +
.../as7116-54x/classes/__init__.py | 0
.../as7116-54x/classes/fanutil.py | 0
.../as7116-54x/classes/thermalutil.py | 0
.../as7116-54x/modules/Makefile | 2 +
.../modules/x86-64-accton-as7116-54x-cpld.c | 242 +++
.../modules/x86-64-accton-as7116-54x-fan.c | 494 ++++++
.../modules/x86-64-accton-as7116-54x-led.c | 448 ++++++
.../modules/x86-64-accton-as7116-54x-psu.c | 349 +++++
.../modules/x86-64-accton-as7116-54x-sfp.c | 1384 +++++++++++++++++
.../service/as7116-platform-init.service | 13 +
.../as7116-54x/setup.py | 15 +
.../as7116-54x/utils/README | 60 +
.../as7116-54x/utils/accton_as7116_util.py | 518 ++++++
.../debian/changelog | 6 +
.../debian/compat | 1 +
.../debian/control | 11 +
.../debian/rules | 86 +
29 files changed, 5037 insertions(+), 1 deletion(-)
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config_as7116.ini
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/installer.conf
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/minigraph.xml
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py
create mode 100644 device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py
create mode 100644 platform/nephos/sonic-platform-modules-accton/LICENSE
create mode 100644 platform/nephos/sonic-platform-modules-accton/README.md
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/__init__.py
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/fanutil.py
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/thermalutil.py
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c
create mode 100755 platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service
create mode 100644 platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py
create mode 100755 platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README
create mode 100755 platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py
create mode 100755 platform/nephos/sonic-platform-modules-accton/debian/changelog
create mode 100644 platform/nephos/sonic-platform-modules-accton/debian/compat
create mode 100755 platform/nephos/sonic-platform-modules-accton/debian/control
create mode 100755 platform/nephos/sonic-platform-modules-accton/debian/rules
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini
new file mode 100644
index 000000000000..6e5276fc726b
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config.ini
@@ -0,0 +1,58 @@
+# name lanes alias index
+Ethernet0 8 Ethernet1/1 0
+Ethernet1 9 Ethernet2/1 1
+Ethernet2 10 Ethernet3/1 2
+Ethernet3 11 Ethernet4/1 3
+Ethernet4 12 Ethernet5/1 4
+Ethernet5 13 Ethernet6/1 5
+Ethernet6 14 Ethernet7/1 6
+Ethernet7 15 Ethernet8/1 7
+Ethernet8 16 Ethernet9/1 8
+Ethernet9 17 Ethernet10/1 9
+Ethernet10 18 Ethernet11/1 10
+Ethernet11 19 Ethernet12/1 11
+Ethernet12 20 Ethernet13/1 12
+Ethernet13 21 Ethernet14/1 13
+Ethernet14 22 Ethernet15/1 14
+Ethernet15 23 Ethernet16/1 15
+Ethernet16 32 Ethernet17/1 16
+Ethernet17 33 Ethernet18/1 17
+Ethernet18 34 Ethernet19/1 18
+Ethernet19 35 Ethernet20/1 19
+Ethernet20 40 Ethernet21/1 20
+Ethernet21 41 Ethernet22/1 21
+Ethernet22 42 Ethernet23/1 22
+Ethernet23 43 Ethernet24/1 23
+Ethernet24 48 Ethernet25/1 24
+Ethernet25 49 Ethernet26/1 25
+Ethernet26 50 Ethernet27/1 26
+Ethernet27 51 Ethernet28/1 27
+Ethernet28 56 Ethernet29/1 28
+Ethernet29 57 Ethernet30/1 29
+Ethernet30 58 Ethernet31/1 30
+Ethernet31 59 Ethernet32/1 31
+Ethernet32 64 Ethernet33/1 32
+Ethernet33 65 Ethernet34/1 33
+Ethernet34 66 Ethernet35/1 34
+Ethernet35 67 Ethernet36/1 35
+Ethernet36 68 Ethernet37/1 36
+Ethernet37 69 Ethernet38/1 37
+Ethernet38 70 Ethernet39/1 38
+Ethernet39 71 Ethernet40/1 39
+Ethernet40 72 Ethernet41/1 40
+Ethernet41 73 Ethernet42/1 41
+Ethernet42 74 Ethernet43/1 42
+Ethernet43 75 Ethernet44/1 43
+Ethernet44 76 Ethernet45/1 44
+Ethernet45 77 Ethernet46/1 45
+Ethernet46 78 Ethernet47/1 46
+Ethernet47 79 Ethernet48/1 47
+Ethernet48 80 Ethernet49/1 48
+Ethernet49 81 Ethernet50/1 49
+Ethernet50 82 Ethernet51/1 50
+Ethernet51 83 Ethernet52/1 51
+Ethernet52 84,85,86,87 Ethernet53/1 52
+Ethernet53 104,105,106,107 Ethernet54/1 53
+Ethernet54 108,109,110,111 Ethernet55/1 54
+Ethernet55 112,113,114,115 Ethernet56/1 55
+Ethernet56 116,117,118,119 Ethernet57/1 56
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config_as7116.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config_as7116.ini
new file mode 100644
index 000000000000..0c124743d9ec
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/port_config_as7116.ini
@@ -0,0 +1,55 @@
+# name lanes alias index
+Ethernet0 8 Ethernet1/1 0
+Ethernet1 9 Ethernet2/1 1
+Ethernet2 10 Ethernet3/1 2
+Ethernet3 11 Ethernet4/1 3
+Ethernet4 12 Ethernet5/1 4
+Ethernet5 13 Ethernet6/1 5
+Ethernet6 14 Ethernet7/1 6
+Ethernet7 15 Ethernet8/1 7
+Ethernet8 16 Ethernet9/1 8
+Ethernet9 17 Ethernet10/1 9
+Ethernet10 18 Ethernet11/1 10
+Ethernet11 19 Ethernet12/1 11
+Ethernet12 20 Ethernet13/1 12
+Ethernet13 21 Ethernet14/1 13
+Ethernet14 22 Ethernet15/1 14
+Ethernet15 23 Ethernet16/1 15
+Ethernet16 32 Ethernet17/1 16
+Ethernet17 33 Ethernet18/1 17
+Ethernet18 34 Ethernet19/1 18
+Ethernet19 35 Ethernet20/1 19
+Ethernet20 40 Ethernet21/1 20
+Ethernet21 41 Ethernet22/1 21
+Ethernet22 42 Ethernet23/1 22
+Ethernet23 43 Ethernet24/1 23
+Ethernet24 48 Ethernet25/1 24
+Ethernet25 49 Ethernet26/1 25
+Ethernet26 50 Ethernet27/1 26
+Ethernet27 51 Ethernet28/1 27
+Ethernet28 56 Ethernet29/1 28
+Ethernet29 57 Ethernet30/1 29
+Ethernet30 58 Ethernet31/1 30
+Ethernet31 59 Ethernet32/1 31
+Ethernet32 64 Ethernet33/1 32
+Ethernet33 65 Ethernet34/1 33
+Ethernet34 66 Ethernet35/1 34
+Ethernet35 67 Ethernet36/1 35
+Ethernet36 68 Ethernet37/1 36
+Ethernet37 69 Ethernet38/1 37
+Ethernet38 70 Ethernet39/1 38
+Ethernet39 71 Ethernet40/1 39
+Ethernet40 72 Ethernet41/1 40
+Ethernet41 73 Ethernet42/1 41
+Ethernet42 74 Ethernet43/1 42
+Ethernet43 75 Ethernet44/1 43
+Ethernet44 76 Ethernet45/1 44
+Ethernet45 77 Ethernet46/1 45
+Ethernet46 78 Ethernet47/1 46
+Ethernet47 79 Ethernet48/1 47
+Ethernet48 80,81,82,83 Ethernet49/1 48
+Ethernet49 84,85,86,87 Ethernet50/1 49
+Ethernet50 104,105,106,107 Ethernet51/1 50
+Ethernet51 108,109,110,111 Ethernet52/1 51
+Ethernet52 112,113,114,115 Ethernet53/1 52
+Ethernet53 116,117,118,119 Ethernet54/1 56
\ No newline at end of file
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile
new file mode 100644
index 000000000000..d43b2a33f42d
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/etc/nps/tau-as7116-4806.cfg
+SAI_DSH_CONFIG_FILE=/etc/nps/tau-as7116-4806.dsh
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/installer.conf b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf
new file mode 100644
index 000000000000..925a32fc0c3a
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf
@@ -0,0 +1,3 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps b/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps
new file mode 100644
index 000000000000..9a97d94c0b0e
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/led_proc_init.nps
@@ -0,0 +1,20 @@
+#This configuration file is for customer init value feature. Please refer to mtk_cfg.h/mtk_cfg.c for detail.
+#1. The lines beginning with # are comment lines. The lines beginning with number are the setting lines.
+#2. There are five parameters which can be set.
+# 1) the first is unit.
+# 2) the second is NPS_CFG_TYPE_XXX. Refer to NPS_CFG_TYPE_T.
+# 3) the 3-5 are {param0, param1, value} pairs. Refer to NPS_CFG_VALUE_T. Support HEX format.
+# 4) the (unit, NPS_CFG_TYPE_XXX, param0, param1) group is the key to get the correspingding value.
+# There should be no same (unit, NPS_CFG_TYPE_XXX, param0, param1) group.
+#3. User must follow correct format to apply the setting. Please refer to below commentted example(#0 NPS_CFG_TYPE_L2_ADDR_MODE 0 0 1);
+#4. Usage under the linux shell:
+# 1) ./image-path/image-name -c cfg-path/NPS_Ari_EVB_24.cfg : mamually specify directory path if they are not in current work dirctory.
+# 2) ./image-name -c NPS_Ari_EVB_24.cfg : the image and the NPS_Ari_EVB_24.cfg are in the current work directory.
+
+#unit NPS_CFG_TYPE_XXX param0 param1 value
+#---- ---------------- ------ ------ -----
+0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1
+0 NPS_CFG_TYPE_LED_CFG 0 0 3
+0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1
+0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1
+0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/minigraph.xml b/device/accton/x86_64-accton_as7116_54x-r0/minigraph.xml
new file mode 100644
index 000000000000..d538a8cbd709
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/minigraph.xml
@@ -0,0 +1,1074 @@
+
+
+
+
+
+ ARISTA01T0
+ 10.1.1.33
+ switch1
+ 10.0.0.32
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.0
+ ARISTA01T2
+ 10.0.0.1
+ 1
+ 180
+ 60
+
+
+ ARISTA02T0
+ 10.0.0.35
+ switch1
+ 10.0.0.34
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.2
+ ARISTA02T2
+ 10.0.0.3
+ 1
+ 180
+ 60
+
+
+ ARISTA03T0
+ 10.0.0.37
+ switch1
+ 10.0.0.36
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.4
+ ARISTA03T2
+ 10.0.0.5
+ 1
+ 180
+ 60
+
+
+ ARISTA04T0
+ 10.0.0.39
+ switch1
+ 10.0.0.38
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.6
+ ARISTA04T2
+ 10.0.0.7
+ 1
+ 180
+ 60
+
+
+ ARISTA05T0
+ 10.0.0.41
+ switch1
+ 10.0.0.40
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.8
+ ARISTA05T2
+ 10.0.0.9
+ 1
+ 180
+ 60
+
+
+ ARISTA06T0
+ 10.0.0.43
+ switch1
+ 10.0.0.42
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.10
+ ARISTA06T2
+ 10.0.0.11
+ 1
+ 180
+ 60
+
+
+ ARISTA07T0
+ 10.0.0.45
+ switch1
+ 10.0.0.44
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.12
+ ARISTA07T2
+ 10.0.0.13
+ 1
+ 180
+ 60
+
+
+ ARISTA08T0
+ 10.0.0.47
+ switch1
+ 10.0.0.46
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.14
+ ARISTA08T2
+ 10.0.0.15
+ 1
+ 180
+ 60
+
+
+ ARISTA09T0
+ 10.0.0.49
+ switch1
+ 10.0.0.48
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.16
+ ARISTA09T2
+ 10.0.0.17
+ 1
+ 180
+ 60
+
+
+ ARISTA10T0
+ 10.0.0.51
+ switch1
+ 10.0.0.50
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.18
+ ARISTA10T2
+ 10.0.0.19
+ 1
+ 180
+ 60
+
+
+ ARISTA11T0
+ 10.0.0.53
+ switch1
+ 10.0.0.52
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.20
+ ARISTA11T2
+ 10.0.0.21
+ 1
+ 180
+ 60
+
+
+ ARISTA12T0
+ 10.0.0.55
+ switch1
+ 10.0.0.54
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.22
+ ARISTA12T2
+ 10.0.0.23
+ 1
+ 180
+ 60
+
+
+ ARISTA13T0
+ 10.0.0.57
+ switch1
+ 10.0.0.56
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.24
+ ARISTA13T2
+ 10.0.0.25
+ 1
+ 180
+ 60
+
+
+ ARISTA14T0
+ 10.0.0.59
+ switch1
+ 10.0.0.58
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.26
+ ARISTA14T2
+ 10.0.0.27
+ 1
+ 180
+ 60
+
+
+ ARISTA15T0
+ 10.0.0.61
+ switch1
+ 10.0.0.60
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.28
+ ARISTA15T2
+ 10.0.0.29
+ 1
+ 180
+ 60
+
+
+ ARISTA16T0
+ 10.0.0.63
+ switch1
+ 10.0.0.62
+ 1
+ 180
+ 60
+
+
+ switch1
+ 10.0.0.30
+ ARISTA16T2
+ 10.0.0.31
+ 1
+ 180
+ 60
+
+
+
+
+ 65100
+ switch1
+
+
+ 10.0.0.33
+
+
+
+
+ 10.0.0.1
+
+
+
+
+ 10.0.0.35
+
+
+
+
+ 10.0.0.3
+
+
+
+
+ 10.0.0.37
+
+
+
+
+ 10.0.0.5
+
+
+
+
+ 10.0.0.39
+
+
+
+
+ 10.0.0.7
+
+
+
+
+ 10.0.0.41
+
+
+
+
+ 10.0.0.9
+
+
+
+
+ 10.0.0.43
+
+
+
+
+ 10.0.0.11
+
+
+
+
+ 10.0.0.45
+
+
+
+
+ 10.0.0.13
+
+
+
+
+ 10.0.0.47
+
+
+
+
+ 10.0.0.15
+
+
+
+
+ 10.0.0.49
+
+
+
+
+ 10.0.0.17
+
+
+
+
+ 10.0.0.51
+
+
+
+
+ 10.0.0.19
+
+
+
+
+ 10.0.0.53
+
+
+
+
+ 10.0.0.21
+
+
+
+
+ 10.0.0.55
+
+
+
+
+ 10.0.0.23
+
+
+
+
+ 10.0.0.57
+
+
+
+
+ 10.0.0.25
+
+
+
+
+ 10.0.0.59
+
+
+
+
+ 10.0.0.27
+
+
+
+
+ 10.0.0.61
+
+
+
+
+ 10.0.0.29
+
+
+
+
+ 10.0.0.63
+
+
+
+
+ 10.0.0.31
+
+
+
+
+
+
+
+ 64001
+ ARISTA01T0
+
+
+
+ 65200
+ ARISTA01T2
+
+
+
+ 64002
+ ARISTA02T0
+
+
+
+ 65200
+ ARISTA02T2
+
+
+
+ 64003
+ ARISTA03T0
+
+
+
+ 65200
+ ARISTA03T2
+
+
+
+ 64004
+ ARISTA04T0
+
+
+
+ 65200
+ ARISTA04T2
+
+
+
+ 64005
+ ARISTA05T0
+
+
+
+ 65200
+ ARISTA05T2
+
+
+
+ 64006
+ ARISTA06T0
+
+
+
+ 65200
+ ARISTA06T2
+
+
+
+ 64007
+ ARISTA07T0
+
+
+
+ 65200
+ ARISTA07T2
+
+
+
+ 64008
+ ARISTA08T0
+
+
+
+ 65200
+ ARISTA08T2
+
+
+
+ 64009
+ ARISTA09T0
+
+
+
+ 65200
+ ARISTA09T2
+
+
+
+ 64010
+ ARISTA10T0
+
+
+
+ 65200
+ ARISTA10T2
+
+
+
+ 64011
+ ARISTA11T0
+
+
+
+ 65200
+ ARISTA11T2
+
+
+
+ 64012
+ ARISTA12T0
+
+
+
+ 65200
+ ARISTA12T2
+
+
+
+ 64013
+ ARISTA13T0
+
+
+
+ 65200
+ ARISTA13T2
+
+
+
+ 64014
+ ARISTA14T0
+
+
+
+ 65200
+ ARISTA14T2
+
+
+
+ 64015
+ ARISTA15T0
+
+
+
+ 65200
+ ARISTA15T2
+
+
+
+ 64016
+ ARISTA16T0
+
+
+
+ 65200
+ ARISTA16T2
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+
+
+
+
+
+ switch1
+
+
+
+
+
+ Ethernet0
+ 10.0.0.0/31
+
+
+
+ Ethernet4
+ 10.0.0.2/31
+
+
+
+ Ethernet8
+ 10.0.0.4/31
+
+
+
+ Ethernet12
+ 10.0.0.6/31
+
+
+
+ Ethernet16
+ 10.0.0.8/31
+
+
+
+ Ethernet20
+ 10.0.0.10/31
+
+
+
+ Ethernet24
+ 10.0.0.12/31
+
+
+
+ Ethernet28
+ 10.0.0.14/31
+
+
+
+ Ethernet32
+ 10.0.0.16/31
+
+
+
+ Ethernet36
+ 10.0.0.18/31
+
+
+
+ Ethernet40
+ 10.0.0.20/31
+
+
+
+ Ethernet44
+ 10.0.0.22/31
+
+
+
+ Ethernet48
+ 10.0.0.24/31
+
+
+
+ Ethernet52
+ 10.0.0.26/31
+
+
+
+ Ethernet56
+ 10.0.0.28/31
+
+
+
+ Ethernet60
+ 10.0.0.30/31
+
+
+
+ Ethernet64
+ 10.0.0.32/31
+
+
+
+ Ethernet68
+ 10.0.0.34/31
+
+
+
+ Ethernet72
+ 10.0.0.36/31
+
+
+
+ Ethernet76
+ 10.0.0.38/31
+
+
+
+ Ethernet80
+ 10.0.0.40/31
+
+
+
+ Ethernet84
+ 10.0.0.42/31
+
+
+
+ Ethernet88
+ 10.0.0.44/31
+
+
+
+ Ethernet92
+ 10.0.0.46/31
+
+
+
+ Ethernet96
+ 10.0.0.48/31
+
+
+
+ Ethernet100
+ 10.0.0.50/31
+
+
+
+ Ethernet104
+ 10.0.0.52/31
+
+
+
+ Ethernet108
+ 10.0.0.54/31
+
+
+
+ Ethernet112
+ 10.0.0.56/31
+
+
+
+ Ethernet116
+ 10.0.0.58/31
+
+
+
+ Ethernet120
+ 10.0.0.60/31
+
+
+
+ Ethernet124
+ 10.0.0.62/31
+
+
+
+
+
+
+
+
+
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet0
+ ARISTA01T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet4
+ ARISTA02T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet8
+ ARISTA03T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet12
+ ARISTA04T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet16
+ ARISTA05T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet20
+ ARISTA06T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet24
+ ARISTA07T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet28
+ ARISTA08T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet32
+ ARISTA09T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet36
+ ARISTA10T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet40
+ ARISTA11T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet44
+ ARISTA12T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet48
+ ARISTA13T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet52
+ ARISTA14T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet56
+ ARISTA15T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet60
+ ARISTA16T2
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet64
+ ARISTA01T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet68
+ ARISTA02T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet72
+ ARISTA03T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet76
+ ARISTA04T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet80
+ ARISTA05T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet84
+ ARISTA06T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet88
+ ARISTA07T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet92
+ ARISTA08T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet96
+ ARISTA09T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet100
+ ARISTA10T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet104
+ ARISTA11T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet108
+ ARISTA12T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet112
+ ARISTA13T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet116
+ ARISTA14T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet120
+ ARISTA15T0
+ Ethernet1
+
+
+ DeviceInterfaceLink
+ switch1
+ Ethernet124
+ ARISTA16T0
+ Ethernet1
+
+
+
+
+ switch1
+ Accton-AS7116-54X
+
+
+
+
+
+
+ switch1
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ switch1
+ Accton-AS7116-54X
+
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..1e7d1046d93d
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+try:
+ import exceptions
+ import binascii
+ import time
+ import optparse
+ import warnings
+ import os
+ import sys
+ from sonic_eeprom import eeprom_base
+ from sonic_eeprom import eeprom_tlvinfo
+ import subprocess
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+ _TLV_INFO_MAX_LEN = 256
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py
new file mode 100644
index 000000000000..974bedc4db19
--- /dev/null
+++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform specific SfpUtill class"""
+
+ _port_start = 0
+ _port_end = 53
+ _qsfp_port_start = 48
+ _ports_in_block = 54
+
+ _port_to_eeprom_mapping = {}
+ _port_to_i2c_mapping = {
+ 0 : 37,
+ 1 : 38,
+ 2 : 39,
+ 3 : 40,
+ 4 : 41,
+ 5 : 42,
+ 6 : 43,
+ 7 : 44,
+ 8 : 45,
+ 9 : 46,
+ 10 : 47,
+ 11 : 48,
+ 12 : 49,
+ 13 : 50,
+ 14 : 51,
+ 15 : 52,
+ 16 : 53,
+ 17 : 54,
+ 18 : 55,
+ 19 : 56,
+ 20 : 57,
+ 21 : 58,
+ 22 : 59,
+ 23 : 60,
+ 24 : 61,
+ 25 : 62,
+ 26 : 63,
+ 27 : 64,
+ 28 : 65,
+ 29 : 66,
+ 30 : 67,
+ 31 : 68,
+ 32 : 69,
+ 33 : 70,
+ 34 : 71,
+ 35 : 72,
+ 36 : 73,
+ 37 : 74,
+ 38 : 75,
+ 39 : 76,
+ 40 : 77,
+ 41 : 78,
+ 42 : 79,
+ 43 : 80,
+ 44 : 81,
+ 45 : 82,
+ 46 : 83,
+ 47 : 84,
+ 48 : 21,
+ 49 : 22,
+ 50 : 23,
+ 51 : 24,
+ 52 : 25,
+ 53 : 26,
+ }
+
+ _qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
+
+ def __init__(self):
+ eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
+ for x in range(self._port_start, self._port_end + 1):
+ port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
+ if x == 53:
+ self._port_to_eeprom_mapping[56] = port_eeprom_path # ugly!!!!
+ else:
+ self._port_to_eeprom_mapping[x] = port_eeprom_path
+
+ SfpUtilBase.__init__(self)
+
+ def reset(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps, 'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ #toggle reset
+ reg_file.seek(0)
+ reg_file.write('1')
+ time.sleep(1)
+ reg_file.seek(0)
+ reg_file.write('0')
+ reg_file.close()
+ return True
+
+ def set_low_power_mode(self, port_nuM, lpmode):
+ raise NotImplementedError
+
+ def get_low_power_mode(self, port_num):
+ raise NotImplementedError
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = reg_file.readline().rstrip()
+ if reg_value == '1':
+ return True
+
+ return False
+
+ @property
+ def port_start(self):
+ return self._port_start
+
+ @property
+ def port_end(self):
+ return self._port_end
+
+ @property
+ def qsfp_ports(self):
+ return self._qsfp_ports
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+
diff --git a/platform/nephos/one-image.mk b/platform/nephos/one-image.mk
index 8e9406dca89c..aa5cc1ff4324 100644
--- a/platform/nephos/one-image.mk
+++ b/platform/nephos/one-image.mk
@@ -5,6 +5,7 @@ $(SONIC_ONE_IMAGE)_MACHINE = nephos
$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie
$(SONIC_ONE_IMAGE)_INSTALLS += $(NEPHOS_NPS_KERNEL)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) \
- $(INGRASYS_S9230_64X_PLATFORM_MODULE)
+ $(INGRASYS_S9230_64X_PLATFORM_MODULE) \
+ $(ACCTON_AS7116_54X_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES)
SONIC_INSTALLERS += $(SONIC_ONE_IMAGE)
diff --git a/platform/nephos/rules.mk b/platform/nephos/rules.mk
index 96f39ef8aad1..bf77ad0e6edf 100644
--- a/platform/nephos/rules.mk
+++ b/platform/nephos/rules.mk
@@ -1,6 +1,7 @@
include $(PLATFORM_PATH)/sdk.mk
include $(PLATFORM_PATH)/sai.mk
include $(PLATFORM_PATH)/platform-modules-ingrasys.mk
+include $(PLATFORM_PATH)/platform-modules-accton.mk
include $(PLATFORM_PATH)/docker-orchagent-nephos.mk
include $(PLATFORM_PATH)/docker-syncd-nephos.mk
include $(PLATFORM_PATH)/docker-syncd-nephos-rpc.mk
diff --git a/platform/nephos/sonic-platform-modules-accton/LICENSE b/platform/nephos/sonic-platform-modules-accton/LICENSE
new file mode 100644
index 000000000000..bc693f7a4c40
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/LICENSE
@@ -0,0 +1,16 @@
+Copyright (C) 2016 Microsoft, Inc
+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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/platform/nephos/sonic-platform-modules-accton/README.md b/platform/nephos/sonic-platform-modules-accton/README.md
new file mode 100644
index 000000000000..0ff20bb2d21b
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/README.md
@@ -0,0 +1 @@
+platform drivers of Accton products for the SONiC project
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/__init__.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/fanutil.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/fanutil.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/thermalutil.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/classes/thermalutil.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile
new file mode 100644
index 000000000000..19c7029f14a2
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile
@@ -0,0 +1,2 @@
+obj-m := x86-64-accton-as7116-54x-cpld.o x86-64-accton-as7116-54x-fan.o \
+ x86-64-accton-as7116-54x-led.o x86-64-accton-as7116-54x-psu.o x86-64-accton-as7116-54x-sfp.o
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c
new file mode 100644
index 000000000000..eb52512343a8
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c
@@ -0,0 +1,242 @@
+/*
+ * A hwmon driver for the as7116_54x_cpld
+ *
+ * Copyright (C) 2017 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
+
+static LIST_HEAD(cpld_client_list);
+static struct mutex list_lock;
+
+struct cpld_client_node {
+ struct i2c_client *client;
+ struct list_head list;
+};
+
+/* Addresses scanned for as7116_54x_cpld
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int val = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ val = i2c_smbus_read_byte_data(client, 0x1);
+
+ if (val < 0) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val);
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL);
+
+static void as7116_54x_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 as7116_54x_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 int as7116_54x_cpld_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
+ status = -EIO;
+ goto exit;
+ }
+
+ status = sysfs_create_file(&client->dev.kobj, &ver.attr);
+ if (status) {
+ goto exit;
+ }
+
+ dev_info(&client->dev, "chip found\n");
+ as7116_54x_cpld_add_client(client);
+
+ return 0;
+
+exit:
+ return status;
+}
+
+static int as7116_54x_cpld_remove(struct i2c_client *client)
+{
+ sysfs_remove_file(&client->dev.kobj, &ver.attr);
+ as7116_54x_cpld_remove_client(client);
+
+ return 0;
+}
+
+enum cpld_chips
+{
+ as7116_54x_cpld1,
+ as7116_54x_cpld2,
+ as7116_54x_cpld3
+};
+
+static const struct i2c_device_id as7116_54x_cpld_id[] = {
+ { "as7116_54x_cpld1", as7116_54x_cpld1 },
+ { "as7116_54x_cpld2", as7116_54x_cpld2 },
+ { "as7116_54x_cpld3", as7116_54x_cpld3 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as7116_54x_cpld_id);
+
+static struct i2c_driver as7116_54x_cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "as7116_54x_cpld",
+ },
+ .probe = as7116_54x_cpld_probe,
+ .remove = as7116_54x_cpld_remove,
+ .id_table = as7116_54x_cpld_id,
+ .address_list = normal_i2c,
+};
+
+int as7116_54x_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 = i2c_smbus_read_byte_data(cpld_node->client, reg);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as7116_54x_cpld_read);
+
+int as7116_54x_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 = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as7116_54x_cpld_write);
+
+static int __init as7116_54x_cpld_init(void)
+{
+ mutex_init(&list_lock);
+ return i2c_add_driver(&as7116_54x_cpld_driver);
+}
+
+static void __exit as7116_54x_cpld_exit(void)
+{
+ i2c_del_driver(&as7116_54x_cpld_driver);
+}
+
+static struct dmi_system_id as7116_54x_dmi_table[] = {
+ {
+ .ident = "Accton AS7716",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AS7116"),
+ },
+ }
+};
+
+int platform_accton_as7116_54x(void)
+{
+ //return dmi_check_system(as7116_54x_dmi_table);
+ return 1;
+}
+EXPORT_SYMBOL(platform_accton_as7116_54x);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("accton_as7116_54x driver");
+MODULE_LICENSE("GPL");
+
+module_init(as7116_54x_cpld_init);
+module_exit(as7116_54x_cpld_exit);
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c
new file mode 100644
index 000000000000..4fd1b91e26dc
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c
@@ -0,0 +1,494 @@
+/*
+ * A hwmon driver for the Accton as7716 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
+
+#define DRVNAME "as7116_54x_fan"
+
+static struct as7116_54x_fan_data *as7116_54x_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);
+
+/* fan related data, the index should match sysfs_fan_attributes
+ */
+static const u8 fan_reg[] = {
+ 0x02, /* fan 1-6 present status */
+ 0x03, /* fan 1-6 direction(0:F2B 1:B2F) */
+ 0x06, /* fan PWM(for all fan) */
+ 0x04, /* front fan fault */
+ 0x05, /* rear fan fault */
+ 0x07, /* front fan 1 speed(rpm) */
+ 0x08, /* front fan 2 speed(rpm) */
+ 0x09, /* front fan 3 speed(rpm) */
+ 0x0A, /* front fan 4 speed(rpm) */
+ 0x0B, /* front fan 5 speed(rpm) */
+ 0x0C, /* rear fan 1 speed(rpm) */
+ 0x0D, /* rear fan 2 speed(rpm) */
+ 0x0E, /* rear fan 3 speed(rpm) */
+ 0x0f, /* rear fan 4 speed(rpm) */
+ 0x10, /* rear fan 5 speed(rpm) */
+};
+
+/* Each client has this additional data */
+struct as7116_54x_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 */
+};
+
+enum fan_id {
+ FAN1_ID,
+ FAN2_ID,
+ FAN3_ID,
+ FAN4_ID,
+ FAN5_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 */
+ FAN_FRONT_FAULT_REG,
+ FAN_REAR_FAULT_REG,
+ FAN1_FRONT_SPEED_RPM,
+ FAN2_FRONT_SPEED_RPM,
+ FAN3_FRONT_SPEED_RPM,
+ FAN4_FRONT_SPEED_RPM,
+ FAN5_FRONT_SPEED_RPM,
+ FAN1_REAR_SPEED_RPM,
+ FAN2_REAR_SPEED_RPM,
+ FAN3_REAR_SPEED_RPM,
+ FAN4_REAR_SPEED_RPM,
+ FAN5_REAR_SPEED_RPM,
+ FAN1_DIRECTION,
+ FAN2_DIRECTION,
+ FAN3_DIRECTION,
+ FAN4_DIRECTION,
+ FAN5_DIRECTION,
+ FAN1_PRESENT,
+ FAN2_PRESENT,
+ FAN3_PRESENT,
+ FAN4_PRESENT,
+ FAN5_PRESENT,
+ FAN1_FRONT_FAULT,
+ FAN2_FRONT_FAULT,
+ FAN3_FRONT_FAULT,
+ FAN4_FRONT_FAULT,
+ FAN5_FRONT_FAULT,
+ FAN1_REAR_FAULT,
+ FAN2_REAR_FAULT,
+ FAN3_REAR_FAULT,
+ FAN4_REAR_FAULT,
+ FAN5_REAR_FAULT
+};
+
+/* Define attributes
+ */
+#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_front_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_FAULT);\
+ static SENSOR_DEVICE_ATTR(fan##index##_rear_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_FAULT)
+#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_front_fault.dev_attr.attr,\
+ &sensor_dev_attr_fan##index##_rear_fault.dev_attr.attr
+
+#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION)
+#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
+
+#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
+#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
+
+#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
+#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
+
+#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \
+ 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)
+#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
+ &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
+
+/* 6 fan fault attributes in this platform */
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5);
+/* 6 fan speed(rpm) attributes in this platform */
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
+/* 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);
+/* 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);
+/* 1 fan duty cycle attribute in this platform */
+DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
+
+static struct attribute *as7116_54x_fan_attributes[] = {
+ /* fan related attributes */
+ DECLARE_FAN_FAULT_ATTR(1),
+ DECLARE_FAN_FAULT_ATTR(2),
+ DECLARE_FAN_FAULT_ATTR(3),
+ DECLARE_FAN_FAULT_ATTR(4),
+ DECLARE_FAN_FAULT_ATTR(5),
+ DECLARE_FAN_SPEED_RPM_ATTR(1),
+ DECLARE_FAN_SPEED_RPM_ATTR(2),
+ DECLARE_FAN_SPEED_RPM_ATTR(3),
+ DECLARE_FAN_SPEED_RPM_ATTR(4),
+ DECLARE_FAN_SPEED_RPM_ATTR(5),
+ DECLARE_FAN_PRESENT_ATTR(1),
+ DECLARE_FAN_PRESENT_ATTR(2),
+ DECLARE_FAN_PRESENT_ATTR(3),
+ DECLARE_FAN_PRESENT_ATTR(4),
+ DECLARE_FAN_PRESENT_ATTR(5),
+ DECLARE_FAN_DIRECTION_ATTR(1),
+ DECLARE_FAN_DIRECTION_ATTR(2),
+ DECLARE_FAN_DIRECTION_ATTR(3),
+ DECLARE_FAN_DIRECTION_ATTR(4),
+ DECLARE_FAN_DIRECTION_ATTR(5),
+ DECLARE_FAN_DUTY_CYCLE_ATTR(),
+ NULL
+};
+
+#define FAN_DUTY_CYCLE_REG_MASK 0x1F
+#define FAN_MIN_DUTY_CYCLE 20
+#define FAN_MAX_DUTY_CYCLE 100
+#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150
+
+static int as7116_54x_fan_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int as7116_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* fan utility functions
+ */
+static u32 reg_val_to_duty_cycle(u8 reg_val)
+{
+ return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5;
+}
+
+static u8 duty_cycle_to_reg_val(u8 duty_cycle)
+{
+ return (duty_cycle / 5);
+}
+
+static u32 reg_val_to_speed_rpm(u8 reg_val)
+{
+ return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
+}
+
+static u8 reg_val_to_direction(u8 reg_val, enum fan_id id)
+{
+ return !!(reg_val & (1 << id));
+}
+
+static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
+{
+ return !(reg_val & (1 << id));
+}
+
+static u8 is_fan_fault(u8 reg_val, enum fan_id id)
+{
+ return !!(reg_val & (1 << id));
+}
+#if 0
+static u8 is_fan_fault(struct as7116_54x_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;
+}
+#endif
+
+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 < FAN_MIN_DUTY_CYCLE) {
+ value = FAN_MIN_DUTY_CYCLE;
+ }
+
+ if (value > FAN_MAX_DUTY_CYCLE) {
+ value = FAN_MAX_DUTY_CYCLE;
+ }
+
+ as7116_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
+ return count;
+}
+
+static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as7116_54x_fan_data *data = as7116_54x_fan_update_device(dev);
+ ssize_t ret = 0;
+
+ if (data->valid) {
+ switch (attr->index) {
+ case FAN_DUTY_CYCLE_PERCENTAGE:
+ {
+ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
+ ret = sprintf(buf, "%u\n", duty_cycle);
+ break;
+ }
+ case FAN1_FRONT_SPEED_RPM:
+ case FAN2_FRONT_SPEED_RPM:
+ case FAN3_FRONT_SPEED_RPM:
+ case FAN4_FRONT_SPEED_RPM:
+ case FAN5_FRONT_SPEED_RPM:
+ case FAN1_REAR_SPEED_RPM:
+ case FAN2_REAR_SPEED_RPM:
+ case FAN3_REAR_SPEED_RPM:
+ case FAN4_REAR_SPEED_RPM:
+ case FAN5_REAR_SPEED_RPM:
+ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
+ break;
+ case FAN1_PRESENT:
+ case FAN2_PRESENT:
+ case FAN3_PRESENT:
+ case FAN4_PRESENT:
+ case FAN5_PRESENT:
+ ret = sprintf(buf, "%d\n",
+ reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
+ attr->index - FAN1_PRESENT));
+ break;
+ case FAN1_FRONT_FAULT:
+ case FAN2_FRONT_FAULT:
+ case FAN3_FRONT_FAULT:
+ case FAN4_FRONT_FAULT:
+ case FAN5_FRONT_FAULT:
+ ret = sprintf(buf, "%d\n",
+ is_fan_fault(data->reg_val[FAN_FRONT_FAULT_REG],
+ attr->index - FAN1_FRONT_FAULT));
+ break;
+ case FAN1_REAR_FAULT:
+ case FAN2_REAR_FAULT:
+ case FAN3_REAR_FAULT:
+ case FAN4_REAR_FAULT:
+ case FAN5_REAR_FAULT:
+ ret = sprintf(buf, "%d\n",
+ is_fan_fault(data->reg_val[FAN_REAR_FAULT_REG],
+ attr->index - FAN1_REAR_FAULT));
+ break;
+ case FAN1_DIRECTION:
+ case FAN2_DIRECTION:
+ case FAN3_DIRECTION:
+ case FAN4_DIRECTION:
+ case FAN5_DIRECTION:
+ ret = sprintf(buf, "%d\n",
+ reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG],
+ attr->index - FAN1_DIRECTION));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static const struct attribute_group as7116_54x_fan_group = {
+ .attrs = as7116_54x_fan_attributes,
+};
+
+static struct as7116_54x_fan_data *as7116_54x_fan_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7116_54x_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 as7116_54x_fan update\n");
+ data->valid = 0;
+
+ /* Update fan data
+ */
+ for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
+ int status = as7116_54x_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 as7116_54x_fan_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as7116_54x_fan_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as7116_54x_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, &as7116_54x_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, &as7116_54x_fan_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as7116_54x_fan_remove(struct i2c_client *client)
+{
+ struct as7116_54x_fan_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as7116_54x_fan_group);
+
+ return 0;
+}
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END };
+
+static const struct i2c_device_id as7116_54x_fan_id[] = {
+ { "as7116_54x_fan", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as7116_54x_fan_id);
+
+static struct i2c_driver as7116_54x_fan_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = DRVNAME,
+ },
+ .probe = as7116_54x_fan_probe,
+ .remove = as7116_54x_fan_remove,
+ .id_table = as7116_54x_fan_id,
+ .address_list = normal_i2c,
+};
+
+static int __init as7116_54x_fan_init(void)
+{
+#if 0
+ extern int platform_accton_as7116_54x(void);
+ if (!platform_accton_as7116_54x()) {
+ return -ENODEV;
+ }
+#endif
+ return i2c_add_driver(&as7116_54x_fan_driver);
+}
+
+static void __exit as7116_54x_fan_exit(void)
+{
+ i2c_del_driver(&as7116_54x_fan_driver);
+}
+
+module_init(as7116_54x_fan_init);
+module_exit(as7116_54x_fan_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("as7116_54x_fan driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c
new file mode 100644
index 000000000000..cd69f711c826
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c
@@ -0,0 +1,448 @@
+/*
+ * A LED driver for the accton_as7116_54x_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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRVNAME "as7116_54x_fan"
+
+#define DEBUG_MODE 0
+#if (DEBUG_MODE == 1)
+ #define DEBUG_PRINT(fmt, args...) \
+ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
+#else
+ #define DEBUG_PRINT(fmt, args...)
+#endif
+
+extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+struct as7116_54x_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]; /* LOC/DIAG LED */
+};
+
+static struct as7116_54x_led_data *ledctl = NULL;
+
+/* LED related data
+ */
+
+#define LED_CNTRLER_I2C_ADDRESS (0x60)
+
+#define LED_TYPE_DIAG_REG_MASK (0x0C)
+#define LED_MODE_DIAG_GREEN_VALUE (0x08)
+#define LED_MODE_DIAG_AMBER_VALUE (0x04)
+#define LED_MODE_DIAG_YELLOW_VALUE (0x00)
+#define LED_MODE_DIAG_OFF_VALUE (0x0C)
+
+#define LED_TYPE_FAN_REG_MASK (0x03)
+#define LED_MODE_FAN_GREEN_VALUE (0x02)
+#define LED_MODE_FAN_AMBER_VALUE (0x01)
+#define LED_MODE_FAN_OFF_VALUE (0x03)
+#define LED_MODE_FAN_AUTO_VALUE (0x00)
+
+#define LED_TYPE_PSU1_REG_MASK (0x03)
+#define LED_MODE_PSU1_GREEN_VALUE (0x02)
+#define LED_MODE_PSU1_AMBER_VALUE (0x01)
+#define LED_MODE_PSU1_OFF_VALUE (0x03)
+#define LED_MODE_PSU1_AUTO_VALUE (0x00)
+
+#define LED_TYPE_PSU2_REG_MASK (0x0C)
+#define LED_MODE_PSU2_GREEN_VALUE (0x08)
+#define LED_MODE_PSU2_AMBER_VALUE (0x04)
+#define LED_MODE_PSU2_OFF_VALUE (0x0C)
+#define LED_MODE_PSU2_AUTO_VALUE (0x00)
+
+#define LED_TYPE_LOC_REG_MASK (0x30)
+#define LED_MODE_LOC_AMBER_VALUE (0x00)
+#define LED_MODE_LOC_AMBER_BLINKING_VALUE1 (0x20)
+#define LED_MODE_LOC_AMBER_BLINKING_VALUE2 (0x30)
+#define LED_MODE_LOC_OFF_VALUE (0x10)
+
+static const u8 led_reg[] = {
+ 0x0A, /* LOC/DIAG/FAN LED */
+ 0x0B, /* PSU1/PSU2 LED */
+};
+
+enum led_type {
+ LED_TYPE_DIAG,
+ LED_TYPE_LOC,
+ LED_TYPE_FAN,
+ LED_TYPE_PSU1,
+ LED_TYPE_PSU2
+};
+
+enum led_light_mode {
+ LED_MODE_OFF = 0,
+ LED_MODE_GREEN,
+ LED_MODE_GREEN_BLINK,
+ LED_MODE_AMBER,
+ LED_MODE_AMBER_BLINK,
+ LED_MODE_YELLOW,
+ LED_MODE_YELLOW_BLINK,
+ LED_MODE_BLUE,
+ LED_MODE_BLUE_BLINK,
+ LED_MODE_AUTO,
+ LED_MODE_UNKNOWN
+};
+
+struct led_type_mode {
+ enum led_type type;
+ enum led_light_mode mode;
+ int type_mask;
+ int mode_value;
+};
+
+static struct led_type_mode led_type_mode_data[] = {
+{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE},
+{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE},
+{LED_TYPE_FAN, LED_MODE_AMBER, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AMBER_VALUE},
+{LED_TYPE_FAN, LED_MODE_AUTO, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AUTO_VALUE},
+{LED_TYPE_PSU1, LED_MODE_OFF, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_OFF_VALUE},
+{LED_TYPE_PSU1, LED_MODE_GREEN, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_GREEN_VALUE},
+{LED_TYPE_PSU1, LED_MODE_AMBER, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AMBER_VALUE},
+{LED_TYPE_PSU1, LED_MODE_AUTO, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AUTO_VALUE},
+{LED_TYPE_PSU2, LED_MODE_OFF, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_OFF_VALUE},
+{LED_TYPE_PSU2, LED_MODE_GREEN, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_GREEN_VALUE},
+{LED_TYPE_PSU2, LED_MODE_AMBER, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AMBER_VALUE},
+{LED_TYPE_PSU2, LED_MODE_AUTO, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AUTO_VALUE},
+{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
+{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
+{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
+{LED_TYPE_DIAG, LED_MODE_YELLOW, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_YELLOW_VALUE},
+{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
+{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE},
+{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE1},
+{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE2}
+};
+
+static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
+ if (type != led_type_mode_data[i].type) {
+ continue;
+ }
+
+ if ((led_type_mode_data[i].type_mask & reg_val) ==
+ led_type_mode_data[i].mode_value) {
+ return led_type_mode_data[i].mode;
+ }
+ }
+
+ return LED_MODE_UNKNOWN;
+}
+
+static u8 led_light_mode_to_reg_val(enum led_type type,
+ enum led_light_mode mode, u8 reg_val) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
+ int type_mask, mode_value;
+
+ if (type != led_type_mode_data[i].type)
+ continue;
+
+ if (mode != led_type_mode_data[i].mode)
+ continue;
+
+ type_mask = led_type_mode_data[i].type_mask;
+ mode_value = led_type_mode_data[i].mode_value;
+ reg_val = (reg_val & ~type_mask) | mode_value;
+ }
+
+ return reg_val;
+}
+
+static int as7116_54x_led_read_value(u8 reg)
+{
+ return as7116_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
+}
+
+static int as7116_54x_led_write_value(u8 reg, u8 value)
+{
+ return as7116_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
+}
+
+static void as7116_54x_led_update(void)
+{
+ mutex_lock(&ledctl->update_lock);
+
+ if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
+ || !ledctl->valid) {
+ int i;
+
+ dev_dbg(&ledctl->pdev->dev, "Starting accton_as7116_54x_led update\n");
+ ledctl->valid = 0;
+
+ /* Update LED data
+ */
+ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
+ int status = as7116_54x_led_read_value(led_reg[i]);
+
+ if (status < 0) {
+ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
+ goto exit;
+ }
+ else {
+ ledctl->reg_val[i] = status;
+ }
+ }
+
+ ledctl->last_updated = jiffies;
+ ledctl->valid = 1;
+ }
+
+exit:
+ mutex_unlock(&ledctl->update_lock);
+}
+
+static void as7116_54x_led_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode,
+ u8 reg, enum led_type type)
+{
+ int reg_val;
+
+ mutex_lock(&ledctl->update_lock);
+
+ reg_val = as7116_54x_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);
+ as7116_54x_led_write_value(reg, reg_val);
+
+ /* to prevent the slow-update issue */
+ ledctl->valid = 0;
+
+exit:
+ mutex_unlock(&ledctl->update_lock);
+}
+
+
+static void as7116_54x_led_diag_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG);
+}
+
+static enum led_brightness as7116_54x_led_diag_get(struct led_classdev *cdev)
+{
+ as7116_54x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
+}
+
+static void as7116_54x_led_loc_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC);
+}
+
+static enum led_brightness as7116_54x_led_loc_get(struct led_classdev *cdev)
+{
+ as7116_54x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
+}
+
+static void as7116_54x_led_fan_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN);
+}
+
+static enum led_brightness as7116_54x_led_fan_get(struct led_classdev *cdev)
+{
+ as7116_54x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]);
+}
+
+static void as7116_54x_led_psu1_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1);
+}
+
+static enum led_brightness as7116_54x_led_psu1_get(struct led_classdev *cdev)
+{
+ as7116_54x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]);
+}
+
+static void as7116_54x_led_psu2_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2);
+}
+
+static enum led_brightness as7116_54x_led_psu2_get(struct led_classdev *cdev)
+{
+ as7116_54x_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]);
+}
+
+static struct led_classdev as7116_54x_leds[] = {
+ [LED_TYPE_DIAG] = {
+ .name = "as7116_54x_led::diag",
+ .default_trigger = "unused",
+ .brightness_set = as7116_54x_led_diag_set,
+ .brightness_get = as7116_54x_led_diag_get,
+ .max_brightness = LED_MODE_YELLOW,
+ },
+ [LED_TYPE_LOC] = {
+ .name = "as7116_54x_led::loc",
+ .default_trigger = "unused",
+ .brightness_set = as7116_54x_led_loc_set,
+ .brightness_get = as7116_54x_led_loc_get,
+ .max_brightness = LED_MODE_AMBER_BLINK,
+ },
+ [LED_TYPE_FAN] = {
+ .name = "as7116_54x_led::fan",
+ .default_trigger = "unused",
+ .brightness_set = as7116_54x_led_fan_set,
+ .brightness_get = as7116_54x_led_fan_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_PSU1] = {
+ .name = "as7116_54x_led::psu1",
+ .default_trigger = "unused",
+ .brightness_set = as7116_54x_led_psu1_set,
+ .brightness_get = as7116_54x_led_psu1_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_PSU2] = {
+ .name = "as7116_54x_led::psu2",
+ .default_trigger = "unused",
+ .brightness_set = as7116_54x_led_psu2_set,
+ .brightness_get = as7116_54x_led_psu2_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+};
+
+
+static int as7116_54x_led_probe(struct platform_device *pdev)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) {
+ ret = led_classdev_register(&pdev->dev, &as7116_54x_leds[i]);
+
+ if (ret < 0) {
+ break;
+ }
+ }
+
+ /* Check if all LEDs were successfully registered */
+ if (i != ARRAY_SIZE(as7116_54x_leds)){
+ int j;
+
+ /* only unregister the LEDs that were successfully registered */
+ for (j = 0; j < i; j++) {
+ led_classdev_unregister(&as7116_54x_leds[i]);
+ }
+ }
+
+ return ret;
+}
+
+static int as7116_54x_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) {
+ led_classdev_unregister(&as7116_54x_leds[i]);
+ }
+
+ return 0;
+}
+
+static struct platform_driver as7116_54x_led_driver = {
+ .probe = as7116_54x_led_probe,
+ .remove = as7116_54x_led_remove,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init as7116_54x_led_init(void)
+{
+ int ret;
+
+#if 0
+ extern int platform_accton_as7116_54x(void);
+ if (!platform_accton_as7116_54x()) {
+ return -ENODEV;
+ }
+#endif
+
+ ret = platform_driver_register(&as7116_54x_led_driver);
+ if (ret < 0) {
+ goto exit;
+ }
+
+ ledctl = kzalloc(sizeof(struct as7116_54x_led_data), GFP_KERNEL);
+ if (!ledctl) {
+ ret = -ENOMEM;
+ goto exit_driver;
+ }
+
+ mutex_init(&ledctl->update_lock);
+
+ ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+ if (IS_ERR(ledctl->pdev)) {
+ ret = PTR_ERR(ledctl->pdev);
+ goto exit_free;
+ }
+
+ return 0;
+
+exit_free:
+ kfree(ledctl);
+exit_driver:
+ platform_driver_unregister(&as7116_54x_led_driver);
+exit:
+ return ret;
+}
+
+static void __exit as7116_54x_led_exit(void)
+{
+ platform_device_unregister(ledctl->pdev);
+ platform_driver_unregister(&as7116_54x_led_driver);
+ kfree(ledctl);
+}
+
+module_init(as7116_54x_led_init);
+module_exit(as7116_54x_led_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("accton_as7116_54x_led driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c
new file mode 100644
index 000000000000..b4e14297f414
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c
@@ -0,0 +1,349 @@
+/*
+ * An hwmon driver for accton as7116_54x Power Module
+ *
+ * Copyright (C) 2014 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * Based on ad7414.c
+ * Copyright 2006 Stefan Roese , DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define PSU_STATUS_I2C_ADDR 0x60
+#define PSU_STATUS_I2C_REG_OFFSET 0x2
+
+#define MODEL_NAME_LEN 11
+#define MODEL_NAME_REG_OFFSET 0x20
+
+#define SERIAL_NUM_LEN 18
+#define SERIAL_NUM_REG_OFFSET 0x35
+
+#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1)))
+#define IS_PRESENT(id, value) (!(value & BIT(id*4)))
+
+static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf);
+static int as7116_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
+extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg);
+static struct as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom);
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Each client has this additional data
+ */
+struct as7116_54x_psu_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 index; /* PSU index */
+ u8 status; /* Status(present/power_good) register read from CPLD */
+ char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */
+ char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/
+};
+
+enum as7116_54x_psu_sysfs_attributes {
+ PSU_PRESENT,
+ PSU_MODEL_NAME,
+ PSU_POWER_GOOD,
+ PSU_SERIAL_NUMBER
+};
+
+/* sysfs attributes for hwmon
+ */
+static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
+static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME);
+static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
+static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER);
+
+static struct attribute *as7116_54x_psu_attributes[] = {
+ &sensor_dev_attr_psu_present.dev_attr.attr,
+ &sensor_dev_attr_psu_model_name.dev_attr.attr,
+ &sensor_dev_attr_psu_power_good.dev_attr.attr,
+ &sensor_dev_attr_psu_serial_numer.dev_attr.attr,
+ NULL
+};
+
+static ssize_t show_status(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 0);
+ u8 status = 0;
+
+ if (!data->valid) {
+ return -EIO;
+ }
+
+ if (attr->index == PSU_PRESENT) {
+ status = IS_PRESENT(data->index, data->status);
+ }
+ else { /* PSU_POWER_GOOD */
+ status = IS_POWER_GOOD(data->index, data->status);
+ }
+
+ return sprintf(buf, "%d\n", status);
+}
+
+static ssize_t show_string(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 1);
+ char *ptr = NULL;
+
+ if (!data->valid) {
+ return -EIO;
+ }
+
+ if (!IS_PRESENT(data->index, data->status)) {
+ return -ENXIO;
+ }
+
+ if (attr->index == PSU_MODEL_NAME) {
+ ptr = data->model_name;
+ }
+ else { /* PSU_SERIAL_NUBMER */
+ ptr = data->serial;
+ }
+
+ return sprintf(buf, "%s\n", ptr);
+}
+
+static const struct attribute_group as7116_54x_psu_group = {
+ .attrs = as7116_54x_psu_attributes,
+};
+
+static int as7116_54x_psu_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as7116_54x_psu_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as7116_54x_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, &as7116_54x_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, &as7116_54x_psu_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as7116_54x_psu_remove(struct i2c_client *client)
+{
+ struct as7116_54x_psu_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as7116_54x_psu_group);
+ kfree(data);
+
+ return 0;
+}
+
+enum psu_index
+{
+ as7116_54x_psu1,
+ as7116_54x_psu2
+};
+
+static const struct i2c_device_id as7116_54x_psu_id[] = {
+ { "as7116_54x_psu1", as7116_54x_psu1 },
+ { "as7116_54x_psu2", as7116_54x_psu2 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as7116_54x_psu_id);
+
+static struct i2c_driver as7116_54x_psu_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "as7116_54x_psu",
+ },
+ .probe = as7116_54x_psu_probe,
+ .remove = as7116_54x_psu_remove,
+ .id_table = as7116_54x_psu_id,
+ .address_list = normal_i2c,
+};
+
+static int as7116_54x_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 as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as7116_54x_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;
+
+ data->valid = 0;
+ dev_dbg(&client->dev, "Starting as7116_54x update\n");
+
+ /* Read psu status */
+ status = as7116_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
+
+ if (status < 0) {
+ dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
+ goto exit;
+ }
+ else {
+ data->status = status;
+ }
+
+
+ memset(data->model_name, 0, sizeof(data->model_name));
+ memset(data->serial, 0, sizeof(data->serial));
+
+ if (update_eeprom && IS_PRESENT(data->index, data->status)) {
+ /* Read model name */
+ status = as7116_54x_psu_read_block(client, MODEL_NAME_REG_OFFSET, data->model_name,
+ ARRAY_SIZE(data->model_name)-1);
+
+ if (status < 0) {
+ data->model_name[0] = '\0';
+ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
+ goto exit;
+ }
+ else {
+ /* Skip the meaningless data byte 8*/
+ data->model_name[8] = data->model_name[9];
+ data->model_name[9] = data->model_name[10];
+ data->model_name[10] = '\0';
+ }
+
+ /* Read serial number */
+ status = as7116_54x_psu_read_block(client, SERIAL_NUM_REG_OFFSET, data->serial,
+ ARRAY_SIZE(data->serial)-1);
+
+ if (status < 0) {
+ data->serial[0] = '\0';
+ dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr);
+ goto exit;
+ }
+ else {
+ data->serial[SERIAL_NUM_LEN] = '\0';
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+static int __init as7116_54x_psu_init(void)
+{
+ //extern int platform_accton_as7116_54x(void);
+ //if (!platform_accton_as7116_54x()) {
+ // return -ENODEV;
+ //}
+
+ return i2c_add_driver(&as7116_54x_psu_driver);
+}
+
+static void __exit as7116_54x_psu_exit(void)
+{
+ i2c_del_driver(&as7116_54x_psu_driver);
+}
+
+module_init(as7116_54x_psu_init);
+module_exit(as7116_54x_psu_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("as7116_54x_psu driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c
new file mode 100644
index 000000000000..540ceb21722f
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c
@@ -0,0 +1,1384 @@
+/*
+ * SFP driver for accton as7116_54x sfp
+ *
+ * Copyright (C) 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
+
+#define DRIVER_NAME "as7116_54x_sfp" /* Platform dependent */
+
+#define DEBUG_MODE 0
+
+#if (DEBUG_MODE == 1)
+ #define DEBUG_PRINT(fmt, args...) \
+ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
+#else
+ #define DEBUG_PRINT(fmt, args...)
+#endif
+
+#define EEPROM_NAME "sfp_eeprom"
+#define EEPROM_SIZE 256 /* 256 byte eeprom */
+#define BIT_INDEX(i) (1ULL << (i))
+#define USE_I2C_BLOCK_READ 1 /* Platform dependent */
+#define I2C_RW_RETRY_COUNT 3
+#define I2C_RW_RETRY_INTERVAL 100 /* ms */
+
+#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1)
+#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1)
+
+#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0
+#define SFF8024_DEVICE_ID_SFP 0x3
+#define SFF8024_DEVICE_ID_QSFP 0xC
+#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD
+#define SFF8024_DEVICE_ID_QSFP28 0x11
+
+#define SFF8472_DIAG_MON_TYPE_ADDR 92
+#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40
+#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3
+#define SFF8472_10G_BASE_MASK 0xF0
+
+#define SFF8436_RX_LOS_ADDR 3
+#define SFF8436_TX_FAULT_ADDR 4
+#define SFF8436_TX_DISABLE_ADDR 86
+
+static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
+static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);;
+static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int);
+static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int);
+extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+enum sfp_sysfs_attributes {
+ PRESENT,
+ PRESENT_ALL,
+ PORT_NUMBER,
+ PORT_TYPE,
+ DDM_IMPLEMENTED,
+ TX_FAULT,
+ TX_FAULT1,
+ TX_FAULT2,
+ TX_FAULT3,
+ TX_FAULT4,
+ TX_DISABLE,
+ TX_DISABLE1,
+ TX_DISABLE2,
+ TX_DISABLE3,
+ TX_DISABLE4,
+ RX_LOS,
+ RX_LOS1,
+ RX_LOS2,
+ RX_LOS3,
+ RX_LOS4,
+ RX_LOS_ALL
+};
+
+/* SFP/QSFP common attributes for sysfs */
+static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER);
+static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE);
+static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT);
+static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL);
+static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS);
+static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE);
+static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT);
+
+/* QSFP attributes for sysfs */
+static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1);
+static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2);
+static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3);
+static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4);
+static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1);
+static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2);
+static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3);
+static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4);
+static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1);
+static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2);
+static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3);
+static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4);
+static struct attribute *qsfp_attributes[] = {
+ &sensor_dev_attr_sfp_port_number.dev_attr.attr,
+ &sensor_dev_attr_sfp_port_type.dev_attr.attr,
+ &sensor_dev_attr_sfp_is_present.dev_attr.attr,
+ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los1.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los2.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los3.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los4.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr,
+ NULL
+};
+
+/* SFP msa attributes for sysfs */
+static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED);
+static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL);
+static struct attribute *sfp_msa_attributes[] = {
+ &sensor_dev_attr_sfp_port_number.dev_attr.attr,
+ &sensor_dev_attr_sfp_port_type.dev_attr.attr,
+ &sensor_dev_attr_sfp_is_present.dev_attr.attr,
+ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr,
+ &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los.dev_attr.attr,
+ &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr,
+ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr,
+ NULL
+};
+
+/* SFP ddm attributes for sysfs */
+static struct attribute *sfp_ddm_attributes[] = {
+ NULL
+};
+
+/* Platform dependent +++ */
+#define CPLD_PORT_TO_FRONT_PORT(port) (port+1)
+
+enum port_numbers {
+as7116_54x_sfp1, as7116_54x_sfp2, as7116_54x_sfp3, as7116_54x_sfp4,
+as7116_54x_sfp5, as7116_54x_sfp6, as7116_54x_sfp7, as7116_54x_sfp8,
+as7116_54x_sfp9, as7116_54x_sfp10, as7116_54x_sfp11, as7116_54x_sfp12,
+as7116_54x_sfp13, as7116_54x_sfp14, as7116_54x_sfp15, as7116_54x_sfp16,
+as7116_54x_sfp17, as7116_54x_sfp18, as7116_54x_sfp19, as7116_54x_sfp20,
+as7116_54x_sfp21, as7116_54x_sfp22, as7116_54x_sfp23, as7116_54x_sfp24,
+as7116_54x_sfp25, as7116_54x_sfp26, as7116_54x_sfp27, as7116_54x_sfp28,
+as7116_54x_sfp29, as7116_54x_sfp30, as7116_54x_sfp31, as7116_54x_sfp32,
+as7116_54x_sfp33, as7116_54x_sfp34, as7116_54x_sfp35, as7116_54x_sfp36,
+as7116_54x_sfp37, as7116_54x_sfp38, as7116_54x_sfp39, as7116_54x_sfp40,
+as7116_54x_sfp41, as7116_54x_sfp42, as7116_54x_sfp43, as7116_54x_sfp44,
+as7116_54x_sfp45, as7116_54x_sfp46, as7116_54x_sfp47, as7116_54x_sfp48,
+as7116_54x_sfp49, as7116_54x_sfp50, as7116_54x_sfp51, as7116_54x_sfp52,
+as7116_54x_sfp53, as7116_54x_sfp54
+};
+
+#define I2C_DEV_ID(x) { #x, x}
+
+static const struct i2c_device_id sfp_device_id[] = {
+I2C_DEV_ID(as7116_54x_sfp1),
+I2C_DEV_ID(as7116_54x_sfp2),
+I2C_DEV_ID(as7116_54x_sfp3),
+I2C_DEV_ID(as7116_54x_sfp4),
+I2C_DEV_ID(as7116_54x_sfp5),
+I2C_DEV_ID(as7116_54x_sfp6),
+I2C_DEV_ID(as7116_54x_sfp7),
+I2C_DEV_ID(as7116_54x_sfp8),
+I2C_DEV_ID(as7116_54x_sfp9),
+I2C_DEV_ID(as7116_54x_sfp10),
+I2C_DEV_ID(as7116_54x_sfp11),
+I2C_DEV_ID(as7116_54x_sfp12),
+I2C_DEV_ID(as7116_54x_sfp13),
+I2C_DEV_ID(as7116_54x_sfp14),
+I2C_DEV_ID(as7116_54x_sfp15),
+I2C_DEV_ID(as7116_54x_sfp16),
+I2C_DEV_ID(as7116_54x_sfp17),
+I2C_DEV_ID(as7116_54x_sfp18),
+I2C_DEV_ID(as7116_54x_sfp19),
+I2C_DEV_ID(as7116_54x_sfp20),
+I2C_DEV_ID(as7116_54x_sfp21),
+I2C_DEV_ID(as7116_54x_sfp22),
+I2C_DEV_ID(as7116_54x_sfp23),
+I2C_DEV_ID(as7116_54x_sfp24),
+I2C_DEV_ID(as7116_54x_sfp25),
+I2C_DEV_ID(as7116_54x_sfp26),
+I2C_DEV_ID(as7116_54x_sfp27),
+I2C_DEV_ID(as7116_54x_sfp28),
+I2C_DEV_ID(as7116_54x_sfp29),
+I2C_DEV_ID(as7116_54x_sfp30),
+I2C_DEV_ID(as7116_54x_sfp31),
+I2C_DEV_ID(as7116_54x_sfp32),
+I2C_DEV_ID(as7116_54x_sfp33),
+I2C_DEV_ID(as7116_54x_sfp34),
+I2C_DEV_ID(as7116_54x_sfp35),
+I2C_DEV_ID(as7116_54x_sfp36),
+I2C_DEV_ID(as7116_54x_sfp37),
+I2C_DEV_ID(as7116_54x_sfp38),
+I2C_DEV_ID(as7116_54x_sfp39),
+I2C_DEV_ID(as7116_54x_sfp40),
+I2C_DEV_ID(as7116_54x_sfp41),
+I2C_DEV_ID(as7116_54x_sfp42),
+I2C_DEV_ID(as7116_54x_sfp43),
+I2C_DEV_ID(as7116_54x_sfp44),
+I2C_DEV_ID(as7116_54x_sfp45),
+I2C_DEV_ID(as7116_54x_sfp46),
+I2C_DEV_ID(as7116_54x_sfp47),
+I2C_DEV_ID(as7116_54x_sfp48),
+I2C_DEV_ID(as7116_54x_sfp49),
+I2C_DEV_ID(as7116_54x_sfp50),
+I2C_DEV_ID(as7116_54x_sfp51),
+I2C_DEV_ID(as7116_54x_sfp52),
+I2C_DEV_ID(as7116_54x_sfp53),
+I2C_DEV_ID(as7116_54x_sfp54),
+{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, sfp_device_id);
+
+/*
+ * list of valid port types
+ * note OOM_PORT_TYPE_NOT_PRESENT to indicate no
+ * module is present in this port
+ */
+typedef enum oom_driver_port_type_e {
+ OOM_DRIVER_PORT_TYPE_INVALID,
+ OOM_DRIVER_PORT_TYPE_NOT_PRESENT,
+ OOM_DRIVER_PORT_TYPE_SFP,
+ OOM_DRIVER_PORT_TYPE_SFP_PLUS,
+ OOM_DRIVER_PORT_TYPE_QSFP,
+ OOM_DRIVER_PORT_TYPE_QSFP_PLUS,
+ OOM_DRIVER_PORT_TYPE_QSFP28
+} oom_driver_port_type_t;
+
+enum driver_type_e {
+ DRIVER_TYPE_SFP_MSA,
+ DRIVER_TYPE_SFP_DDM,
+ DRIVER_TYPE_QSFP
+};
+
+/* Each client has this additional data
+ */
+struct eeprom_data {
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ struct bin_attribute bin; /* eeprom data */
+};
+
+struct sfp_msa_data {
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u64 status[6]; /* bit0:port0, bit1:port1 and so on */
+ /* index 0 => tx_fail
+ 1 => tx_disable
+ 2 => rx_loss
+ 3 => device id
+ 4 => 10G Ethernet Compliance Codes
+ to distinguish SFP or SFP+
+ 5 => DIAGNOSTIC MONITORING TYPE */
+ struct eeprom_data eeprom;
+};
+
+struct sfp_ddm_data {
+ struct eeprom_data eeprom;
+};
+
+struct qsfp_data {
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 status[3]; /* bit0:port0, bit1:port1 and so on */
+ /* index 0 => tx_fail
+ 1 => tx_disable
+ 2 => rx_loss */
+
+ u8 device_id;
+ struct eeprom_data eeprom;
+};
+
+struct sfp_port_data {
+ struct mutex update_lock;
+ enum driver_type_e driver_type;
+ int port; /* CPLD port index */
+ oom_driver_port_type_t port_type;
+ u64 present; /* present status, bit0:port0, bit1:port1 and so on */
+
+ struct sfp_msa_data *msa;
+ struct sfp_ddm_data *ddm;
+ struct qsfp_data *qsfp;
+
+ struct i2c_client *client;
+};
+
+static ssize_t show_port_number(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port));
+}
+
+/* Platform dependent +++ */
+static struct sfp_port_data *sfp_update_present(struct i2c_client *client)
+{
+ int i = 0, j = 0, status = -1;
+ u8 reg;
+ unsigned short cpld_addr;
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ DEBUG_PRINT("Starting sfp present status update");
+ mutex_lock(&data->update_lock);
+ data->present = 0;
+
+ /* Read present status of port 1~48(SFP port) */
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 3; j++) {
+ cpld_addr = 0x61+i;
+ reg = 0x6+j;
+ status = as7116_54x_cpld_read(cpld_addr, reg);
+
+ if (unlikely(status < 0)) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status);
+ goto exit;
+ }
+
+ DEBUG_PRINT("Present status = 0x%lx\r\n", data->present);
+ data->present |= (u64)status << ((i*24) + (j%3)*8);
+ }
+ }
+
+ /* Read present status of port 49-54(QSFP port) */
+ cpld_addr = 0x62;
+ reg = 0x14;
+ status = as7116_54x_cpld_read(cpld_addr, reg);
+
+ if (unlikely(status < 0)) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status);
+ goto exit;
+ }
+ else {
+ data->present |= (u64)status << 48;
+ }
+
+ DEBUG_PRINT("Present status = 0x%lx", data->present);
+exit:
+ mutex_unlock(&data->update_lock);
+ return (status < 0) ? ERR_PTR(status) : data;
+}
+
+static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ int i = 0, j = 0;
+ int status = -1;
+
+ if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) {
+ return data;
+ }
+
+ DEBUG_PRINT("Starting as7116_54x sfp tx rx status update");
+ mutex_lock(&data->update_lock);
+ data->msa->valid = 0;
+ memset(data->msa->status, 0, sizeof(data->msa->status));
+
+ /* Read status of port 1~48(SFP port) */
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 9; j++) {
+ u8 reg;
+ unsigned short cpld_addr;
+ reg = 0x9+j;
+ cpld_addr = 0x61+i;
+
+ status = as7116_54x_cpld_read(cpld_addr, reg);
+ if (unlikely(status < 0)) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status);
+ goto exit;
+ }
+
+ data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8);
+ }
+ }
+
+ data->msa->valid = 1;
+ data->msa->last_updated = jiffies;
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return (status < 0) ? ERR_PTR(status) : data;
+}
+
+static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ unsigned short cpld_addr = 0;
+ u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0;
+ long disable;
+ int error;
+
+ if (data->driver_type == DRIVER_TYPE_QSFP) {
+ return qsfp_set_tx_disable(dev, da, buf, count);
+ }
+
+ error = kstrtol(buf, 10, &disable);
+ if (error) {
+ return error;
+ }
+
+ mutex_lock(&data->update_lock);
+
+ if(data->port < 24) {
+ cpld_addr = 0x61;
+ cpld_reg = 0xC + data->port / 8;
+ cpld_bit = 1 << (data->port % 8);
+ }
+ else { /* port 24 ~ 48 */
+ cpld_addr = 0x62;
+ cpld_reg = 0xC + (data->port - 24) / 8;
+ cpld_bit = 1 << (data->port % 8);
+ }
+
+ /* Read current status */
+ cpld_val = as7116_54x_cpld_read(cpld_addr, cpld_reg);
+
+ /* Update tx_disable status */
+ if (disable) {
+ data->msa->status[1] |= BIT_INDEX(data->port);
+ cpld_val |= cpld_bit;
+ }
+ else {
+ data->msa->status[1] &= ~BIT_INDEX(data->port);
+ cpld_val &= ~cpld_bit;
+ }
+
+ as7116_54x_cpld_write(cpld_addr, cpld_reg, cpld_val);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+/* Platform dependent --- */
+
+static int sfp_is_port_present(struct i2c_client *client, int port)
+{
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ data = sfp_update_present(client);
+ if (IS_ERR(data)) {
+ return PTR_ERR(data);
+ }
+
+ return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */
+}
+
+/* Platform dependent +++ */
+static ssize_t show_present(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);
+
+ if (PRESENT_ALL == attr->index) {
+ int i;
+ u8 values[7] = {0};
+ struct sfp_port_data *data = sfp_update_present(client);
+
+ if (IS_ERR(data)) {
+ return PTR_ERR(data);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(values); i++) {
+ values[i] = ~(u8)(data->present >> (i * 8));
+ }
+
+ /* Return values 1 -> 54 in order */
+ return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
+ values[0], values[1], values[2],
+ values[3], values[4], values[5],
+ values[6] & 0x3F);
+ }
+ else {
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ int present = sfp_is_port_present(client, data->port);
+
+ if (IS_ERR_VALUE(present)) {
+ return present;
+ }
+
+ /* PRESENT */
+ return sprintf(buf, "%d\n", present);
+ }
+}
+/* Platform dependent --- */
+
+static struct sfp_port_data *sfp_update_port_type(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ u8 buf = 0;
+ int status;
+
+ mutex_lock(&data->update_lock);
+
+ switch (data->driver_type) {
+ case DRIVER_TYPE_SFP_MSA:
+ {
+ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf));
+ if (unlikely(status < 0)) {
+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID;
+ break;
+ }
+
+ if (buf != SFF8024_DEVICE_ID_SFP) {
+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID;
+ break;
+ }
+
+ status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf));
+ if (unlikely(status < 0)) {
+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID;
+ break;
+ }
+
+ DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf);
+ data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP;
+ break;
+ }
+ case DRIVER_TYPE_QSFP:
+ {
+ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf));
+ if (unlikely(status < 0)) {
+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID;
+ break;
+ }
+
+ DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf);
+ switch (buf) {
+ case SFF8024_DEVICE_ID_QSFP:
+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP;
+ break;
+ case SFF8024_DEVICE_ID_QSFP_PLUS:
+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS;
+ break;
+ case SFF8024_DEVICE_ID_QSFP28:
+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS;
+ break;
+ default:
+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID;
+ break;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return data;
+}
+
+static ssize_t show_port_type(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ int present = sfp_is_port_present(client, data->port);
+
+ if (IS_ERR_VALUE(present)) {
+ return present;
+ }
+
+ if (!present) {
+ /* port is not present */
+ return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT);
+ }
+
+ sfp_update_port_type(dev);
+ return sprintf(buf, "%d\n", data->port_type);
+}
+
+static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+ int i, status = -1;
+ u8 buf = 0;
+ u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR};
+
+ DEBUG_PRINT("");
+ if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) {
+ return data;
+ }
+
+ DEBUG_PRINT("Starting sfp tx rx status update");
+ mutex_lock(&data->update_lock);
+ data->qsfp->valid = 0;
+ memset(data->qsfp->status, 0, sizeof(data->qsfp->status));
+
+ DEBUG_PRINT("");
+ /* Notify device to update tx fault/ tx disable/ rx los status */
+ for (i = 0; i < ARRAY_SIZE(reg); i++) {
+ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf));
+ if (unlikely(status < 0)) {
+ DEBUG_PRINT("");
+ goto exit;
+ }
+ }
+ msleep(200);
+ DEBUG_PRINT("");
+
+ /* Read actual tx fault/ tx disable/ rx los status */
+ for (i = 0; i < ARRAY_SIZE(reg); i++) {
+ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf));
+ if (unlikely(status < 0)) {
+ DEBUG_PRINT("");
+ goto exit;
+ }
+
+ DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]);
+ data->qsfp->status[i] = (buf & 0xF);
+ }
+
+ DEBUG_PRINT("");
+ data->qsfp->valid = 1;
+ data->qsfp->last_updated = jiffies;
+
+exit:
+ DEBUG_PRINT("");
+ mutex_unlock(&data->update_lock);
+ return (status < 0) ? ERR_PTR(status) : data;
+}
+
+static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int present;
+ u8 val = 0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ DEBUG_PRINT("");
+ present = sfp_is_port_present(client, data->port);
+ if (IS_ERR_VALUE(present)) {
+ return present;
+ }
+
+ DEBUG_PRINT("");
+ if (present == 0) {
+ /* port is not present */
+ return -ENODEV;
+ }
+
+ DEBUG_PRINT("");
+ data = qsfp_update_tx_rx_status(dev);
+ DEBUG_PRINT("");
+ if (IS_ERR(data)) {
+ return PTR_ERR(data);
+ }
+
+ DEBUG_PRINT("");
+ switch (attr->index) {
+ case TX_FAULT:
+ val = !!(data->qsfp->status[2] & 0xF);
+ break;
+ case TX_FAULT1:
+ case TX_FAULT2:
+ case TX_FAULT3:
+ case TX_FAULT4:
+ val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1));
+ break;
+ case TX_DISABLE:
+ val = data->qsfp->status[1] & 0xF;
+ break;
+ case TX_DISABLE1:
+ case TX_DISABLE2:
+ case TX_DISABLE3:
+ case TX_DISABLE4:
+ val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1));
+ break;
+ case RX_LOS:
+ val = !!(data->qsfp->status[0] & 0xF);
+ break;
+ case RX_LOS1:
+ case RX_LOS2:
+ case RX_LOS3:
+ case RX_LOS4:
+ val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1));
+ break;
+ default:
+ break;
+ }
+
+ DEBUG_PRINT("");
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ long disable;
+ int status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ status = sfp_is_port_present(client, data->port);
+ if (IS_ERR_VALUE(status)) {
+ return status;
+ }
+
+ if (!status) {
+ /* port is not present */
+ return -ENXIO;
+ }
+
+ status = kstrtol(buf, 10, &disable);
+ if (status) {
+ return status;
+ }
+
+ data = qsfp_update_tx_rx_status(dev);
+ if (IS_ERR(data)) {
+ return PTR_ERR(data);
+ }
+
+ mutex_lock(&data->update_lock);
+
+ if (attr->index == TX_DISABLE) {
+ data->qsfp->status[1] = disable & 0xF;
+ }
+ else {/* TX_DISABLE1 ~ TX_DISABLE4*/
+ if (disable) {
+ data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1));
+ }
+ else {
+ data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1));
+ }
+ }
+
+ DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]);
+ status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1]));
+ if (unlikely(status < 0)) {
+ count = status;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ char ddm;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ status = sfp_is_port_present(client, data->port);
+ if (IS_ERR_VALUE(status)) {
+ return status;
+ }
+
+ if (status == 0) {
+ /* port is not present */
+ return -ENODEV;
+ }
+
+ status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm));
+ if (unlikely(status < 0)) {
+ return status;
+ }
+
+ return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK));
+}
+
+/* Platform dependent +++ */
+static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u8 val = 0, index = 0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ DEBUG_PRINT("driver type = (%d)", data->driver_type);
+ if (data->driver_type == DRIVER_TYPE_QSFP) {
+ DEBUG_PRINT("");
+ return qsfp_show_tx_rx_status(dev, da, buf);
+ }
+
+ DEBUG_PRINT("");
+ data = sfp_update_tx_rx_status(dev);
+ if (IS_ERR(data)) {
+ return PTR_ERR(data);
+ }
+
+ if(attr->index == RX_LOS_ALL) {
+ int i = 0;
+ u8 values[6] = {0};
+
+ for (i = 0; i < ARRAY_SIZE(values); i++) {
+ values[i] = (u8)(data->msa->status[2] >> (i * 8));
+ }
+
+ /** Return values 1 -> 48 in order */
+ return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n",
+ values[0], values[1], values[2],
+ values[3], values[4], values[5]);
+ }
+
+ switch (attr->index) {
+ case TX_FAULT:
+ index = 0;
+ break;
+ case TX_DISABLE:
+ index = 1;
+ break;
+ case RX_LOS:
+ index = 2;
+ break;
+ default:
+ break;
+ }
+
+ val = !!(data->msa->status[index] & BIT_INDEX(data->port));
+ return sprintf(buf, "%d\n", val);
+}
+/* Platform dependent --- */
+static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data,
+ int data_len)
+{
+#if USE_I2C_BLOCK_READ
+ int status, retry = I2C_RW_RETRY_COUNT;
+
+ if (data_len > I2C_SMBUS_BLOCK_MAX) {
+ data_len = I2C_SMBUS_BLOCK_MAX;
+ }
+
+ while (retry) {
+ status = i2c_smbus_write_i2c_block_data(client, command, data_len, data);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ if (unlikely(status < 0)) {
+ return status;
+ }
+
+ return data_len;
+#else
+ int status, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_write_byte_data(client, command, *data);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ if (unlikely(status < 0)) {
+ return status;
+ }
+
+ return 1;
+#endif
+
+
+}
+
+static ssize_t sfp_port_write(struct sfp_port_data *data,
+ const char *buf, loff_t off, size_t count)
+{
+ ssize_t retval = 0;
+
+ if (unlikely(!count)) {
+ return count;
+ }
+
+ /*
+ * Write data to chip, protecting against concurrent updates
+ * from this host, but not from other I2C masters.
+ */
+ mutex_lock(&data->update_lock);
+
+ while (count) {
+ ssize_t status;
+
+ status = sfp_eeprom_write(data->client, off, buf, count);
+ if (status <= 0) {
+ if (retval == 0) {
+ retval = status;
+ }
+ break;
+ }
+ buf += status;
+ off += status;
+ count -= status;
+ retval += status;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return retval;
+}
+
+
+static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ int present;
+ struct sfp_port_data *data;
+ DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count);
+ data = dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+ present = sfp_is_port_present(data->client, data->port);
+ if (IS_ERR_VALUE(present)) {
+ return present;
+ }
+
+ if (present == 0) {
+ /* port is not present */
+ return -ENODEV;
+ }
+
+ return sfp_port_write(data, buf, off, count);
+}
+
+static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data,
+ int data_len)
+{
+#if USE_I2C_BLOCK_READ
+ int status, retry = I2C_RW_RETRY_COUNT;
+
+ if (data_len > I2C_SMBUS_BLOCK_MAX) {
+ data_len = I2C_SMBUS_BLOCK_MAX;
+ }
+
+ while (retry) {
+ status = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ if (unlikely(status < 0)) {
+ goto abort;
+ }
+ if (unlikely(status != data_len)) {
+ status = -EIO;
+ goto abort;
+ }
+
+ //result = data_len;
+
+abort:
+ return status;
+#else
+ int status, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_read_byte_data(client, command);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ if (unlikely(status < 0)) {
+ dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status);
+ goto abort;
+ }
+
+ *data = (u8)status;
+ status = 1;
+
+abort:
+ return status;
+#endif
+}
+
+static ssize_t sfp_port_read(struct sfp_port_data *data,
+ char *buf, loff_t off, size_t count)
+{
+ ssize_t retval = 0;
+
+ if (unlikely(!count)) {
+ DEBUG_PRINT("Count = 0, return");
+ return count;
+ }
+
+ /*
+ * Read data from chip, protecting against concurrent updates
+ * from this host, but not from other I2C masters.
+ */
+ mutex_lock(&data->update_lock);
+
+ while (count) {
+ ssize_t status;
+
+ status = sfp_eeprom_read(data->client, off, buf, count);
+ if (status <= 0) {
+ if (retval == 0) {
+ retval = status;
+ }
+ break;
+ }
+
+ buf += status;
+ off += status;
+ count -= status;
+ retval += status;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return retval;
+
+}
+
+static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ int present;
+ struct sfp_port_data *data;
+ DEBUG_PRINT("offset = (%d), count = (%d)", off, count);
+ data = dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+ present = sfp_is_port_present(data->client, data->port);
+ if (IS_ERR_VALUE(present)) {
+ return present;
+ }
+
+ if (present == 0) {
+ /* port is not present */
+ return -ENODEV;
+ }
+
+ return sfp_port_read(data, buf, off, count);
+}
+
+static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom)
+{
+ int err;
+
+ sysfs_bin_attr_init(eeprom);
+ eeprom->attr.name = EEPROM_NAME;
+ eeprom->attr.mode = S_IWUSR | S_IRUGO;
+ eeprom->read = sfp_bin_read;
+ eeprom->write = sfp_bin_write;
+ eeprom->size = EEPROM_SIZE;
+
+ /* Create eeprom file */
+ err = sysfs_create_bin_file(kobj, eeprom);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+}
+
+static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom)
+{
+ sysfs_remove_bin_file(kobj, eeprom);
+ return 0;
+}
+
+static const struct attribute_group sfp_msa_group = {
+ .attrs = sfp_msa_attributes,
+};
+
+static int sfp_i2c_check_functionality(struct i2c_client *client)
+{
+#if USE_I2C_BLOCK_READ
+ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK);
+#else
+ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA);
+#endif
+}
+
+static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id,
+ struct sfp_msa_data **data)
+{
+ int status;
+ struct sfp_msa_data *msa;
+
+ if (!sfp_i2c_check_functionality(client)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL);
+ if (!msa) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ /* init eeprom */
+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin);
+ if (status) {
+ goto exit_remove;
+ }
+
+ *data = msa;
+ dev_info(&client->dev, "sfp msa '%s'\n", client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group);
+exit_free:
+ kfree(msa);
+exit:
+
+ return status;
+}
+
+static const struct attribute_group sfp_ddm_group = {
+ .attrs = sfp_ddm_attributes,
+};
+
+static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id,
+ struct sfp_ddm_data **data)
+{
+ int status;
+ struct sfp_ddm_data *ddm;
+
+ if (!sfp_i2c_check_functionality(client)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL);
+ if (!ddm) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ /* init eeprom */
+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin);
+ if (status) {
+ goto exit_remove;
+ }
+
+ *data = ddm;
+ dev_info(&client->dev, "sfp ddm '%s'\n", client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group);
+exit_free:
+ kfree(ddm);
+exit:
+
+ return status;
+}
+
+static const struct attribute_group qsfp_group = {
+ .attrs = qsfp_attributes,
+};
+
+static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id,
+ struct qsfp_data **data)
+{
+ int status;
+ struct qsfp_data *qsfp;
+
+ if (!sfp_i2c_check_functionality(client)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL);
+ if (!qsfp) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &qsfp_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ /* init eeprom */
+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin);
+ if (status) {
+ goto exit_remove;
+ }
+
+ /* Bring QSFPs out of reset */
+ as7116_54x_cpld_write(0x62, 0x15, 0x3F);
+
+ *data = qsfp;
+ dev_info(&client->dev, "qsfp '%s'\n", client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &qsfp_group);
+exit_free:
+ kfree(qsfp);
+exit:
+
+ return status;
+}
+
+/* Platform dependent +++ */
+static int sfp_device_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct sfp_port_data *data = NULL;
+
+ data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL);
+ if (!data) {
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->port = dev_id->driver_data;
+ data->client = client;
+
+ if (dev_id->driver_data >= as7116_54x_sfp1 && dev_id->driver_data <= as7116_54x_sfp48) {
+ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) {
+ data->driver_type = DRIVER_TYPE_SFP_MSA;
+ return sfp_msa_probe(client, dev_id, &data->msa);
+ }
+ else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) {
+ data->driver_type = DRIVER_TYPE_SFP_DDM;
+ return sfp_ddm_probe(client, dev_id, &data->ddm);
+ }
+ }
+ else { /* as7116_54x_sfp49 ~ as7116_54x_sfp54 */
+ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) {
+ data->driver_type = DRIVER_TYPE_QSFP;
+ return qsfp_probe(client, dev_id, &data->qsfp);
+ }
+ }
+
+ return -ENODEV;
+}
+/* Platform dependent --- */
+
+static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data)
+{
+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin);
+ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group);
+ kfree(data);
+ return 0;
+}
+
+static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data)
+{
+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin);
+ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group);
+ kfree(data);
+ return 0;
+}
+
+static int qfp_remove(struct i2c_client *client, struct qsfp_data *data)
+{
+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin);
+ sysfs_remove_group(&client->dev.kobj, &qsfp_group);
+ kfree(data);
+ return 0;
+}
+
+static int sfp_device_remove(struct i2c_client *client)
+{
+ struct sfp_port_data *data = i2c_get_clientdata(client);
+
+ switch (data->driver_type) {
+ case DRIVER_TYPE_SFP_MSA:
+ return sfp_msa_remove(client, data->msa);
+ case DRIVER_TYPE_SFP_DDM:
+ return sfp_ddm_remove(client, data->ddm);
+ case DRIVER_TYPE_QSFP:
+ return qfp_remove(client, data->qsfp);
+ }
+
+ return 0;
+}
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static struct i2c_driver sfp_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+ .probe = sfp_device_probe,
+ .remove = sfp_device_remove,
+ .id_table = sfp_device_id,
+ .address_list = normal_i2c,
+};
+
+static int __init sfp_init(void)
+{
+ //extern int platform_accton_as7116_54x(void);
+ //if (!platform_accton_as7116_54x()) {
+ // return -ENODEV;
+ //}
+
+ return i2c_add_driver(&sfp_driver);
+}
+
+static void __exit sfp_exit(void)
+{
+ i2c_del_driver(&sfp_driver);
+}
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("accton as7116_54x_sfp driver");
+MODULE_LICENSE("GPL");
+
+module_init(sfp_init);
+module_exit(sfp_exit);
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service
new file mode 100755
index 000000000000..be8688d2c2d2
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Accton AS7116-54X Platform initialization service
+Before=pmon.service
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/accton_as7116_util.py install
+ExecStop=/usr/local/bin/accton_as7116_util.py clean
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py
new file mode 100644
index 000000000000..bb740409e310
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from setuptools import setup
+os.listdir
+
+setup(
+ name='as7116-54x',
+ version='1.0.0',
+ description='Module to initialize Accton AS7116-54X platforms',
+
+ packages=['as7116-54x'],
+ package_dir={'as7116-54x': 'as7116-54x/classes'},
+ )
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README
new file mode 100755
index 000000000000..0b9fc1633999
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README
@@ -0,0 +1,60 @@
+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 .
+
+To initialize the system, run "accton_as7712_util.py install".
+To clean up the drivers & devices, run "accton_as7712_util.py clean".
+To dump information of sensors, run "accton_as7712_util.py show".
+To dump SFP EEPROM, run "accton_as7712_util.py sff".
+To set fan speed, run "accton_as7712_util.py set fan".
+To enable/disable SFP emission, run "accton_as7712_util.py set sfp".
+To set system LEDs' color, run "accton_as7712_util.py set led"
+For more information, run "accton_as7712_util.py --help".
+
+====================================================================
+Besides applying accton_as7712_util.py to access peripherals, you can
+access peripherals by sysfs nodes directly after the installation is run.
+
+LED controls can be found under /sys/class/leds. The sysfs interface
+color mappings are as follows:
+Brightness:
+ 0 => off
+ 1 => green
+ 2 => amber
+ 3 => red
+ 4 => blue
+
+There are 5 system LEDs, loc, diag, fan, ps1, and ps2.
+They are lit automatically by CPLD, but the loc and diag.
+The loc led has only 1 color, blue.
+The diag one has 3 colors: red, amber, and green.
+
+Fan controls can be found in /sys/bus/i2c/devices/2-0066.
+There are 12 fans inside 6 fan modules.
+All fans share 1 duty setting, ranged from 0~100.
+
+Three temperature sensors are controlled by the lm75 kernel modules.
+They should already be visible under /sys/bus/i2c/drivers/lm75/.
+
+Two power supplies are controlled by the CPLD.
+Here provide their status under
+/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053.
+
+There are 32 QSFP+ modules are equipped.
+Apply "accton_as7712_util.py show" to get their status.
+Apply "accton_as7712_util.py set sfp" to turn on/off light transmission.
+Apply "accton_as7712_util.py sff" to dump EEPROM information.
+Before operating on that QSFP+, please make sure it is well plugged.
+Otherwise, operation is going to fail.
+
diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py
new file mode 100755
index 000000000000..17c56f7beb53
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py
@@ -0,0 +1,518 @@
+#!/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 = 'as7116_54x'
+version = '0.1.0'
+verbose = False
+DEBUG = False
+args = []
+ALL_DEVICE = {}
+DEVICE_NO = {'led':5, 'fan':1, 'thermal':3, 'psu':2, 'sfp':54}
+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-54 {0|1}\" to set sfp# tx_disable"
+ sys.exit(0)
+
+def show_eeprom_help():
+ cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
+ print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
+ sys.exit(0)
+
+def my_log(txt):
+ if DEBUG == True:
+ print "[ROY]"+txt
+ return
+
+def log_os_system(cmd, show):
+ logging.info('Run :'+cmd)
+ status, output = commands.getstatusoutput(cmd)
+ my_log (cmd +"with result:" + str(status))
+ my_log (" output:"+output)
+ if status:
+ logging.info('Failed :'+cmd)
+ if show:
+ print('Failed :'+cmd)
+ return status, output
+
+def driver_check():
+ ret, lsmod = log_os_system("lsmod| grep accton", 0)
+ logging.info('mods:'+lsmod)
+ if len(lsmod) ==0:
+ return False
+ return True
+
+
+
+kos = [
+ 'depmod',
+ 'modprobe i2c_dev',
+ 'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
+ 'modprobe x86-64-accton-as7116-54x-cpld' ,
+ 'modprobe x86-64-accton-as7116-54x-fan' ,
+ 'modprobe x86-64-accton-as7116-54x-psu' ,
+ 'modprobe x86-64-accton-as7116-54x-sfp' ,
+ 'modprobe x86-64-accton-as7116-54x-led' ]
+
+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
+ return 0
+
+def driver_uninstall():
+ global FORCE
+ for i in range(0,len(kos)):
+ rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
+ rm = rm.replace("insmod", "rmmod")
+ status, output = log_os_system(rm, 1)
+ if status:
+ if FORCE == 0:
+ return status
+ return 0
+
+led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::'
+hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']}
+hwmon_nodes = {'led': ['brightness'] }
+hwmon_prefix ={'led': led_prefix}
+
+i2c_prefix = '/sys/bus/i2c/devices/'
+i2c_bus = {'fan': ['1-0063'] ,
+ 'thermal': ['17-004b','19-0049', '20-004a'] ,
+ 'psu': ['10-0050','11-0058'],
+ 'sfp': ['-0050']}
+i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] ,
+ 'thermal': ['hwmon/hwmon*/temp1_input'] ,
+ 'psu': ['psu_present ', 'psu_power_good'] ,
+ 'sfp': ['sfp_is_present ', 'sfp_tx_disable_all']}
+
+sfp_map = [37,38,39,40,
+ 41,42,43,44,45,46,47,48,49,50,
+ 51,52,53,54,55,56,57,58,59,60,
+ 61,62,63,64,65,66,67,68,69,70,
+ 71,72,73,74,75,76,77,78,79,80,
+ 81,82,83,84,
+ 21,22,23,24,25,26]
+
+mknod =[
+ 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device',
+ 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device',
+ 'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-1/new_device',
+ 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device',
+ 'echo as7116_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-1/new_device',
+ 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-17/new_device',
+ 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-19/new_device',
+ 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-20/new_device',
+ 'echo as7116_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-2/new_device',
+ 'echo as7116_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-2/new_device',
+ 'echo as7116_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-2/new_device',
+ 'echo as7116_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-10/new_device',
+ 'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-10/new_device',
+ 'echo as7116_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-11/new_device',
+ 'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-11/new_device',
+ 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device',
+ 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-29/new_device',
+ 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-30/new_device',
+ 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-31/new_device',
+ 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-32/new_device',
+ 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-33/new_device',
+ 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-34/new_device',
+ 'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device']
+
+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(1)
+
+ status, output = log_os_system(mknod[i], 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+
+ for i in range(0,len(sfp_map)):
+ status, output =log_os_system("echo as7116_54x_sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 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/1-0077", 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_check() == False:
+ return False
+ if not device_exist():
+ return False
+ return True
+
+def do_install():
+ print "Checking system...."
+ if driver_check() == False:
+ print "No driver, installing...."
+ status = driver_install()
+ if status:
+ if FORCE == 0:
+ return status
+ else:
+ print PROJECT_NAME.upper()+" drivers detected...."
+ if not device_exist():
+ print "No device, installing...."
+ status = device_install()
+ if status:
+ if FORCE == 0:
+ return status
+ else:
+ print PROJECT_NAME.upper()+" devices detected...."
+ return
+
+def do_uninstall():
+ print "Checking system...."
+ if not device_exist():
+ print PROJECT_NAME.upper() +" has no device installed...."
+ else:
+ print "Removing device...."
+ status = device_uninstall()
+ if status:
+ if FORCE == 0:
+ return status
+
+ if driver_check()== False :
+ print PROJECT_NAME.upper() +" has no driver installed...."
+ else:
+ print "Removing installed driver...."
+ status = driver_uninstall()
+ if status:
+ if FORCE == 0:
+ return status
+
+ return
+
+def devices_info():
+ global DEVICE_NO
+ global ALL_DEVICE
+ global i2c_bus, hwmon_types
+ for key in DEVICE_NO:
+ ALL_DEVICE[key]= {}
+ for i in range(0,DEVICE_NO[key]):
+ ALL_DEVICE[key][key+str(i+1)] = []
+
+ for key in i2c_bus:
+ buses = i2c_bus[key]
+ nodes = i2c_nodes[key]
+ for i in range(0,len(buses)):
+ for j in range(0,len(nodes)):
+ if 'fan' == key:
+ for k in range(0,DEVICE_NO[key]):
+ node = key+str(k+1)
+ path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+ elif 'sfp' == key:
+ for k in range(0,DEVICE_NO[key]):
+ node = key+str(k+1)
+ path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+ else:
+ node = key+str(i+1)
+ path = i2c_prefix+ buses[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+
+ for key in hwmon_types:
+ itypes = hwmon_types[key]
+ nodes = hwmon_nodes[key]
+ for i in range(0,len(itypes)):
+ for j in range(0,len(nodes)):
+ node = key+"_"+itypes[i]
+ path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][ key+str(i+1)].append(path)
+
+ #show dict all in the order
+ if DEBUG == True:
+ for i in sorted(ALL_DEVICE.keys()):
+ print(i+": ")
+ for j in sorted(ALL_DEVICE[i].keys()):
+ print(" "+j)
+ for k in (ALL_DEVICE[i][j]):
+ print(" "+" "+k)
+ return
+
+def show_eeprom(index):
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+ node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
+ node = node.replace(node.split("/")[-1], 'sfp_eeprom')
+ # check if got hexdump command in current environment
+ ret, log = log_os_system("which hexdump", 0)
+ ret, log2 = log_os_system("which busybox hexdump", 0)
+ if len(log):
+ hex_cmd = 'hexdump'
+ elif len(log2):
+ hex_cmd = ' busybox hexdump'
+ else:
+ log = 'Failed : no hexdump cmd!!'
+ logging.info(log)
+ print log
+ return 1
+
+ print node + ":"
+ ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
+ if ret==0:
+ print log
+ else:
+ print "**********device no found**********"
+ return
+
+def set_device(args):
+ global DEVICE_NO
+ global ALL_DEVICE
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+
+ if args[0]=='led':
+ if int(args[1])>4:
+ show_set_help()
+ return
+ #print ALL_DEVICE['led']
+ for i in range(0,len(ALL_DEVICE['led'])):
+ for k in (ALL_DEVICE['led']['led'+str(i+1)]):
+ ret, log = log_os_system("echo "+args[1]+" >"+k, 1)
+ if ret:
+ return ret
+ elif args[0]=='fan':
+ if int(args[1])>100:
+ show_set_help()
+ return
+ #print ALL_DEVICE['fan']
+ #fan1~6 is all fine, all fan share same setting
+ node = ALL_DEVICE['fan'] ['fan1'][0]
+ node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
+ ret, log = log_os_system("cat "+ node, 1)
+ if ret==0:
+ print ("Previous fan duty: " + log.strip() +"%")
+ ret, log = log_os_system("echo "+args[1]+" >"+node, 1)
+ if ret==0:
+ print ("Current fan duty: " + args[1] +"%")
+ return ret
+ elif args[0]=='sfp':
+ if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0:
+ show_set_help()
+ return
+ if len(args)<2:
+ show_set_help()
+ return
+
+ if int(args[2])>1:
+ show_set_help()
+ return
+
+ #print ALL_DEVICE[args[0]]
+ for i in range(0,len(ALL_DEVICE[args[0]])):
+ for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
+ if j.find('tx_disable')!= -1:
+ ret, log = log_os_system("echo "+args[2]+" >"+ j, 1)
+ if ret:
+ return ret
+
+ return
+
+#get digits inside a string.
+#Ex: 31 for "sfp31"
+def get_value(input):
+ digit = re.findall('\d+', input)
+ return int(digit[0])
+
+def device_traversal():
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+ for i in sorted(ALL_DEVICE.keys()):
+ print("============================================")
+ print(i.upper()+": ")
+ print("============================================")
+
+ for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
+ print " "+j+":",
+ for k in (ALL_DEVICE[i][j]):
+ ret, log = log_os_system("cat "+k, 0)
+ func = k.split("/")[-1].strip()
+ func = re.sub(j+'_','',func,1)
+ func = re.sub(i.lower()+'_','',func,1)
+ if ret==0:
+ print func+"="+log+" ",
+ else:
+ print func+"="+"X"+" ",
+ print
+ print("----------------------------------------------------------------")
+
+
+ print
+ return
+
+def device_exist():
+ ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0)
+ ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0)
+ return not(ret1 or ret2)
+
+if __name__ == "__main__":
+ main()
diff --git a/platform/nephos/sonic-platform-modules-accton/debian/changelog b/platform/nephos/sonic-platform-modules-accton/debian/changelog
new file mode 100755
index 000000000000..49f8f44bca48
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/debian/changelog
@@ -0,0 +1,6 @@
+sonic-accton-platform-modules (1.0.0) unstable; urgency=low
+
+ * Add support for AS7116-54X series
+
+ -- developer Wed, 29 Mar 2017 11:00:00 +0800
+
diff --git a/platform/nephos/sonic-platform-modules-accton/debian/compat b/platform/nephos/sonic-platform-modules-accton/debian/compat
new file mode 100644
index 000000000000..ec635144f600
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/platform/nephos/sonic-platform-modules-accton/debian/control b/platform/nephos/sonic-platform-modules-accton/debian/control
new file mode 100755
index 000000000000..e1a403b3a719
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/debian/control
@@ -0,0 +1,11 @@
+Source: sonic-accton-platform-modules
+Section: main
+Priority: extra
+Maintainer: simon.ji@nephosinc.com
+Build-Depends: debhelper (>= 8.0.0), bzip2
+Standards-Version: 3.9.3
+
+Package: sonic-platform-accton-as7116-54x
+Architecture: amd64
+Depends: linux-image-3.16.0-5-amd64
+Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/nephos/sonic-platform-modules-accton/debian/rules b/platform/nephos/sonic-platform-modules-accton/debian/rules
new file mode 100755
index 000000000000..cb232bd42425
--- /dev/null
+++ b/platform/nephos/sonic-platform-modules-accton/debian/rules
@@ -0,0 +1,86 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+include /usr/share/dpkg/pkg-info.mk
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+export INSTALL_MOD_DIR:=extra
+
+PYTHON ?= python2
+
+PACKAGE_PRE_NAME := sonic-platform-accton
+KVERSION ?= $(shell uname -r)
+KERNEL_SRC := /lib/modules/$(KVERSION)
+MOD_SRC_DIR:= $(shell pwd)
+MODULE_DIRS:= as7116-54x
+MODULE_DIR := modules
+UTILS_DIR := utils
+SERVICE_DIR := service
+CLASSES_DIR := classes
+CONF_DIR := conf
+
+%:
+ dh $@ --with systemd,python2,python3 --buildsystem=pybuild
+
+clean:
+ dh_testdir
+ dh_testroot
+ dh_clean
+
+build:
+ #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC)
+ (for mod in $(MODULE_DIRS); do \
+ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
+ $(PYTHON) $${mod}/setup.py build; \
+ done)
+
+binary: binary-arch binary-indep
+ # Nothing to do
+
+binary-arch:
+ # Nothing to do
+
+#install: build
+ #dh_testdir
+ #dh_testroot
+ #dh_clean -k
+ #dh_installdirs
+
+binary-indep:
+ dh_testdir
+ dh_installdirs
+
+ # Custom package commands
+ (for mod in $(MODULE_DIRS); do \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \
+ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
+ cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \
+ $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
+ done)
+ # Resuming debhelper scripts
+ dh_testroot
+ dh_install
+ dh_installchangelogs
+ dh_installdocs
+ dh_systemd_enable
+ dh_installinit
+ dh_systemd_start
+ dh_link
+ dh_fixperms
+ dh_compress
+ dh_strip
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+.PHONY: build binary binary-arch binary-indep clean