diff --git a/.gitignore b/.gitignore
index 9ca9d2ff1a98..c5ed255e62a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ dockers/docker-teamd/Dockerfile
dockers/docker-sonic-mgmt/Dockerfile
platform/*/docker-syncd-*/Dockerfile
platform/*/docker-syncd-*-rpc/Dockerfile
+platform/vs/docker-sonic-vs/Dockerfile
# Installer-related files and directories
installer/x86_64/platforms/
diff --git a/.gitmodules b/.gitmodules
index 4bddfb4a60da..cc2b5b416028 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -44,7 +44,6 @@
[submodule "src/sonic-utilities"]
path = src/sonic-utilities
url = https://github.com/Azure/sonic-utilities
- branch = v1.0.3
[submodule "platform/broadcom/sonic-platform-modules-s6000"]
path = platform/broadcom/sonic-platform-modules-s6000
url = https://github.com/Azure/sonic-platform-modules-s6000
@@ -66,3 +65,6 @@
[submodule "platform/broadcom/sonic-platform-modules-cel"]
path = platform/broadcom/sonic-platform-modules-cel
url = https://github.com/celestica-Inc/sonic-platform-modules-cel.git
+[submodule "src/sonic-frr/frr"]
+ path = src/sonic-frr/frr
+ url = https://github.com/FRRouting/frr.git
diff --git a/Makefile b/Makefile
index d672edc6836a..800cd32093e3 100644
--- a/Makefile
+++ b/Makefile
@@ -25,8 +25,8 @@ $(shell rm -f .screen)
MAKEFLAGS += -B
-SLAVE_BASE_TAG = $(shell shasum sonic-slave/Dockerfile | awk '{print substr($$1,0,11);}')
-SLAVE_TAG = $(shell cat sonic-slave/Dockerfile.user sonic-slave/Dockerfile | shasum | awk '{print substr($$1,0,11);}')
+SLAVE_BASE_TAG = $(shell sha1sum sonic-slave/Dockerfile | awk '{print substr($$1,0,11);}')
+SLAVE_TAG = $(shell cat sonic-slave/Dockerfile.user sonic-slave/Dockerfile | sha1sum | awk '{print substr($$1,0,11);}')
SLAVE_BASE_IMAGE = sonic-slave-base
SLAVE_IMAGE = sonic-slave-$(USER)
@@ -56,11 +56,11 @@ SONIC_BUILD_INSTRUCTION := make \
BUILD_NUMBER=$(BUILD_NUMBER) \
ENABLE_DHCP_GRAPH_SERVICE=$(ENABLE_DHCP_GRAPH_SERVICE) \
SHUTDOWN_BGP_ON_START=$(SHUTDOWN_BGP_ON_START) \
- SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \
+ ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \
PASSWORD=$(PASSWORD) \
USERNAME=$(USERNAME)
-.PHONY: sonic-slave-build sonic-slave-bash
+.PHONY: sonic-slave-build sonic-slave-bash init
.DEFAULT_GOAL := all
@@ -89,3 +89,7 @@ sonic-slave-bash :
{ echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \
$(DOCKER_BUILD) ; }
@$(DOCKER_RUN) -t $(SLAVE_IMAGE):$(SLAVE_TAG) bash
+
+init :
+ git submodule update --init --recursive
+ git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git'
diff --git a/README.md b/README.md
index c3d58ae1b538..bbae2e150b8e 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,12 @@
-Broadcom: [![Broadcom](https://sonic-jenkins.westus.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all)
-Cavium: [![Cavium](https://sonic-jenkins.westus.cloudapp.azure.com/job/cavium/job/buildimage-cavm-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/cavium/job/buildimage-cavm-all/)
-Centec: [![Centec](https://sonic-jenkins.westus.cloudapp.azure.com/job/centec/job/buildimage-centec-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/centec/job/buildimage-centec-all/)
+*master*: Broadcom: [![Broadcom](https://sonic-jenkins.westus.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all)
Mellanox: [![Mellanox](https://sonic-jenkins.westus.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all)
-P4: [![Broadcom](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buildimage-p4-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buildimage-p4-all)
+P4: [![P4](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buildimage-p4-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buildimage-p4-all)
+VS: [![VS](https://sonic-jenkins.westus.cloudapp.azure.com/job/vs/job/buildimage-vs-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/vs/job/buildimage-vs-all)
+
+*201709*: Cavium: [![Cavium](https://sonic-jenkins.westus.cloudapp.azure.com/job/cavium/job/buildimage-cavm-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/cavium/job/buildimage-cavm-all/)
+Centec: [![Centec](https://sonic-jenkins.westus.cloudapp.azure.com/job/centec/job/buildimage-centec-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/centec/job/buildimage-centec-all/)
+Nephos: [![Nephos](https://sonic-jenkins.westus.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all/)
+Marvell: [![Marvell](https://sonic-jenkins.westus.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-all/badge/icon)](https://sonic-jenkins.westus.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-all/)
# sonic-buildimage
@@ -10,7 +14,7 @@ P4: [![Broadcom](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buil
# Description
-Following is the instruction on how to build an [(ONIE)](https://github.com/opencomputeproject/onie) compatiable network operating system (NOS) installer image for network switches, and also how to build docker images running inside the NOS. Note that SONiC image are build per ASIC platform. Switches using the same ASIC platform share a common image. For a list of supported switches and ASIC, please refer to this [document](https://sonic-jenkins.westus.cloudapp.azure.com/job/p4/job/buildimage-p4-all).
+Following is the instruction on how to build an [(ONIE)](https://github.com/opencomputeproject/onie) compatiable network operating system (NOS) installer image for network switches, and also how to build docker images running inside the NOS. Note that SONiC image are build per ASIC platform. Switches using the same ASIC platform share a common image. For a list of supported switches and ASIC, please refer to this [list](https://github.com/Azure/SONiC/wiki/Supported-Devices-and-Platforms)
# Hardware
Any server can be a build image server. We are using a server with 1T hard disk. The OS is Ubuntu 16.04.
@@ -18,26 +22,23 @@ Any server can be a build image server. We are using a server with 1T hard disk.
# Prerequisites
## SAI Version
-SONiC V2 is using [SAI 0.9.4](https://github.com/opencomputeproject/SAI/tree/v0.9.4).
+Please refer to [SONiC roadmap](https://github.com/Azure/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release.
## Clone or fetch the code repository with all git submodules
To clone the code repository recursively, assuming git version 1.9 or newer:
git clone --recursive https://github.com/Azure/sonic-buildimage.git
-NOTE: If the repo has already been cloned, however there are no files under the submodule directories (e.g., src/lldpd, src/ptf, src/sonic-linux-kernel, etc.), you can manually fetch all the git submodules as follows:
-
- git submodule update --init --recursive
-
-You also need to change all git paths to relative path as we build all submodules inside the docker:
-
- git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $(realpath --relative-to=. $(cut -d" " -f2 .git))" > .git'
-
## Usage
To build SONiC installer image and docker images, run the following commands:
+ # Execute make init once after cloning the repo, or fetched remote repo with submodule updates
+ make init
+
+ # Execute make configure once to configure ASIC
make configure PLATFORM=[ASIC_VENDOR]
+
make
**NOTE**: We recommend reserving 50G free space to build one platform.
@@ -45,11 +46,12 @@ To build SONiC installer image and docker images, run the following commands:
The SONiC installer contains all docker images needed. SONiC uses one image for all devices of a same ASIC vendor. The supported ASIC vendors are:
- PLATFORM=broadcom
-- PLATFORM=marvell (*pending*)
+- PLATFORM=marvell
- PLATFORM=mellanox
- PLATFORM=cavium
- PLATFORM=centec
- PLATFORM=p4
+- PLATFORM=vs
For Broadcom ASIC, we build ONIE and EOS image. EOS image is used for Arista devices, ONIE image is used for all other Broadcom ASIC based devices.
@@ -95,6 +97,7 @@ This may take a while, but it is a one-time action, so please be patient.
- docker-syncd-cavm.gz: docker image for the daemon to sync database and Cavium switch ASIC (gzip tar archive)
- docker-syncd-mlnx.gz: docker image for the daemon to sync database and Mellanox switch ASIC (gzip tar archive)
- docker-sonic-p4.gz: docker image for all-in-one for p4 software switch (gzip tar archive)
+ - docker-sonic-vs.gz: docker image for all-in-one for software virtual switch (gzip tar archive)
## Contribution Guide
diff --git a/build_debian.sh b/build_debian.sh
index a21cdada0243..3c6673a53ec4 100755
--- a/build_debian.sh
+++ b/build_debian.sh
@@ -207,7 +207,8 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
kexec-tools \
less \
unzip \
- gdisk
+ gdisk \
+ grub2-common
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \
grub-pc-bin
diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060-CX32S/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060-CX32S/sai.profile
deleted file mode 100644
index 29a42f07a734..000000000000
--- a/device/arista/x86_64-arista_7060_cx32s/Arista-7060-CX32S/sai.profile
+++ /dev/null
@@ -1 +0,0 @@
-SAI_INIT_CONFIG_FILE=/etc/bcm/th-a7060-cx32s-32x100G.config.bcm
diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060-CX32S/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/port_config.ini
similarity index 100%
rename from device/arista/x86_64-arista_7060_cx32s/Arista-7060-CX32S/port_config.ini
rename to device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/port_config.ini
diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile
new file mode 100644
index 000000000000..c04ad3498582
--- /dev/null
+++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/etc/bcm/th-a7060-cx32s-32x100G.config.bcm
diff --git a/device/arista/x86_64-arista_7060_cx32s/minigraph.xml b/device/arista/x86_64-arista_7060_cx32s/minigraph.xml
index 513a60254818..23282de17af1 100644
--- a/device/arista/x86_64-arista_7060_cx32s/minigraph.xml
+++ b/device/arista/x86_64-arista_7060_cx32s/minigraph.xml
@@ -1040,7 +1040,7 @@
switch1
- Arista-7060-CX32S
+ Arista-7060CX-32S-C32
@@ -1075,5 +1075,5 @@
switch1
- Arista-7060-CX32S
+ Arista-7060CX-32S-C32
diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini
index 35a2175cf21d..541b197f6bb8 100644
--- a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini
+++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini
@@ -1,121 +1,121 @@
# name lanes alias index
Ethernet0 77,78 Ethernet1/1 1
-Ethernet2 79,80 Ethernet1/3 2
-Ethernet4 65,66 Ethernet2/1 3
-Ethernet6 67,68 Ethernet2/3 4
-Ethernet8 85,86 Ethernet3/1 5
-Ethernet10 87,88 Ethernet3/3 6
-Ethernet12 89,90 Ethernet4/1 7
-Ethernet14 91,92 Ethernet4/3 8
-Ethernet16 109,110 Ethernet5/1 9
-Ethernet18 111,112 Ethernet5/3 10
-Ethernet20 97,98 Ethernet6/1 11
-Ethernet22 99,100 Ethernet6/3 12
-Ethernet24 5,6 Ethernet7/1 13
-Ethernet26 7,8 Ethernet7/3 14
-Ethernet28 13,14 Ethernet8/1 15
-Ethernet30 15,16 Ethernet8/3 16
-Ethernet32 25,26 Ethernet9/1 17
-Ethernet34 27,28 Ethernet9/3 18
-Ethernet36 21,22 Ethernet10/1 19
-Ethernet38 23,24 Ethernet10/3 20
-Ethernet40 37,38 Ethernet11/1 21
-Ethernet42 39,40 Ethernet11/3 22
-Ethernet44 45,46 Ethernet12/1 23
-Ethernet46 47,48 Ethernet12/3 24
-Ethernet48 57,58 Ethernet13/1 25
-Ethernet50 59,60 Ethernet13/3 26
-Ethernet52 53,54 Ethernet14/1 27
-Ethernet54 55,56 Ethernet14/3 28
-Ethernet56 117,118 Ethernet15/1 29
-Ethernet58 119,120 Ethernet15/3 30
-Ethernet60 121,122 Ethernet16/1 31
-Ethernet62 123,124 Ethernet16/3 32
-Ethernet64 141,142 Ethernet17/1 33
-Ethernet66 143,144 Ethernet17/3 34
-Ethernet68 133,134,135,136 Ethernet18/1 35
-Ethernet72 197,198 Ethernet19/1 36
-Ethernet74 199,200 Ethernet19/3 37
-Ethernet76 205,206,207,208 Ethernet20/1 38
-Ethernet80 217,218 Ethernet21/1 39
-Ethernet82 219,220 Ethernet21/3 40
-Ethernet84 213,214 Ethernet22/1 41
-Ethernet86 215,216 Ethernet22/3 42
-Ethernet88 229,230 Ethernet23/1 43
-Ethernet90 231,232 Ethernet23/3 44
-Ethernet92 237,238 Ethernet24/1 45
-Ethernet94 239,240 Ethernet24/3 46
-Ethernet96 249,250 Ethernet25/1 47
-Ethernet98 251,252 Ethernet25/3 48
-Ethernet100 245,246 Ethernet26/1 49
-Ethernet102 247,248 Ethernet26/3 50
-Ethernet104 149,150 Ethernet27/1 51
-Ethernet106 151,152 Ethernet27/3 52
-Ethernet108 153,154 Ethernet28/1 53
-Ethernet110 155,156 Ethernet28/3 54
-Ethernet112 173,174 Ethernet29/1 55
-Ethernet114 175,176 Ethernet29/3 56
-Ethernet116 161,162 Ethernet30/1 57
-Ethernet118 163,164 Ethernet30/3 58
-Ethernet120 181,182 Ethernet31/1 59
-Ethernet122 183,184 Ethernet31/3 60
-Ethernet124 185,186 Ethernet32/1 61
-Ethernet126 187,188 Ethernet32/3 62
-Ethernet128 69,70 Ethernet33/1 63
-Ethernet130 71,72 Ethernet33/3 64
-Ethernet132 73,74 Ethernet34/1 65
-Ethernet134 75,76 Ethernet34/3 66
-Ethernet136 93,94 Ethernet35/1 67
-Ethernet138 95,96 Ethernet35/3 68
-Ethernet140 81,82 Ethernet36/1 69
-Ethernet142 83,84 Ethernet36/3 70
-Ethernet144 101,102 Ethernet37/1 71
-Ethernet146 103,104 Ethernet37/3 72
-Ethernet148 105,106 Ethernet38/1 73
-Ethernet150 107,108 Ethernet38/3 74
-Ethernet152 9,10 Ethernet39/1 75
-Ethernet154 11,12 Ethernet39/3 76
-Ethernet156 1,2 Ethernet40/1 77
-Ethernet158 3,4 Ethernet40/3 78
-Ethernet160 17,18 Ethernet41/1 79
-Ethernet162 19,20 Ethernet41/3 80
-Ethernet164 29,30 Ethernet42/1 81
-Ethernet166 31,32 Ethernet42/1 82
-Ethernet168 41,42 Ethernet43/1 83
-Ethernet170 43,44 Ethernet43/3 84
-Ethernet172 33,34 Ethernet44/1 85
-Ethernet174 35,36 Ethernet44/3 86
-Ethernet176 49,50,51,52 Ethernet45/1 87
-Ethernet180 61,62,63,64 Ethernet46/1 88
-Ethernet184 125,126,127,128 Ethernet47/1 89
-Ethernet188 113,114,115,116 Ethernet48/1 90
-Ethernet192 129,130,131,132 Ethernet49/1 91
-Ethernet196 137,138,139,140 Ethernet50/1 92
-Ethernet200 201,202,203,204 Ethernet51/1 93
-Ethernet204 193,194,195,196 Ethernet52/1 94
-Ethernet208 209,210 Ethernet53/1 95
-Ethernet210 211,212 Ethernet53/3 96
-Ethernet212 221,222 Ethernet54/1 97
-Ethernet214 223,224 Ethernet54/3 98
-Ethernet216 233,234 Ethernet55/1 99
-Ethernet218 235,236 Ethernet55/3 100
-Ethernet220 225,226 Ethernet56/1 101
-Ethernet222 227,228 Ethernet56/3 102
-Ethernet224 241,242 Ethernet57/1 103
-Ethernet226 243,244 Ethernet57/3 104
-Ethernet228 253,254 Ethernet58/1 105
-Ethernet230 255,256 Ethernet58/3 106
-Ethernet232 157,158 Ethernet59/1 107
-Ethernet234 159,160 Ethernet59/3 108
-Ethernet236 145,146 Ethernet60/1 109
-Ethernet238 147,148 Ethernet60/3 110
-Ethernet240 165,166 Ethernet61/1 111
-Ethernet242 167,168 Ethernet61/3 112
-Ethernet244 169,170 Ethernet62/1 113
-Ethernet246 171,172 Ethernet62/3 114
-Ethernet248 189,190 Ethernet63/1 115
-Ethernet250 191,192 Ethernet63/3 116
-Ethernet252 177,178 Ethernet64/1 117
-Ethernet254 179,180 Ethernet64/3 118
-Ethernet256 257 Ethernet257 119
-Ethernet260 259 Ethernet259 120
+Ethernet2 79,80 Ethernet1/3 1
+Ethernet4 65,66 Ethernet2/1 2
+Ethernet6 67,68 Ethernet2/3 2
+Ethernet8 85,86 Ethernet3/1 3
+Ethernet10 87,88 Ethernet3/3 3
+Ethernet12 89,90 Ethernet4/1 4
+Ethernet14 91,92 Ethernet4/3 4
+Ethernet16 109,110 Ethernet5/1 5
+Ethernet18 111,112 Ethernet5/3 5
+Ethernet20 97,98 Ethernet6/1 6
+Ethernet22 99,100 Ethernet6/3 6
+Ethernet24 5,6 Ethernet7/1 7
+Ethernet26 7,8 Ethernet7/3 7
+Ethernet28 13,14 Ethernet8/1 8
+Ethernet30 15,16 Ethernet8/3 8
+Ethernet32 25,26 Ethernet9/1 9
+Ethernet34 27,28 Ethernet9/3 9
+Ethernet36 21,22 Ethernet10/1 10
+Ethernet38 23,24 Ethernet10/3 10
+Ethernet40 37,38 Ethernet11/1 11
+Ethernet42 39,40 Ethernet11/3 11
+Ethernet44 45,46 Ethernet12/1 12
+Ethernet46 47,48 Ethernet12/3 12
+Ethernet48 57,58 Ethernet13/1 13
+Ethernet50 59,60 Ethernet13/3 13
+Ethernet52 53,54 Ethernet14/1 14
+Ethernet54 55,56 Ethernet14/3 14
+Ethernet56 117,118 Ethernet15/1 15
+Ethernet58 119,120 Ethernet15/3 15
+Ethernet60 121,122 Ethernet16/1 16
+Ethernet62 123,124 Ethernet16/3 16
+Ethernet64 141,142 Ethernet17/1 17
+Ethernet66 143,144 Ethernet17/3 17
+Ethernet68 133,134,135,136 Ethernet18/1 18
+Ethernet72 197,198 Ethernet19/1 19
+Ethernet74 199,200 Ethernet19/3 19
+Ethernet76 205,206,207,208 Ethernet20/1 20
+Ethernet80 217,218 Ethernet21/1 21
+Ethernet82 219,220 Ethernet21/3 21
+Ethernet84 213,214 Ethernet22/1 22
+Ethernet86 215,216 Ethernet22/3 22
+Ethernet88 229,230 Ethernet23/1 23
+Ethernet90 231,232 Ethernet23/3 23
+Ethernet92 237,238 Ethernet24/1 24
+Ethernet94 239,240 Ethernet24/3 24
+Ethernet96 249,250 Ethernet25/1 25
+Ethernet98 251,252 Ethernet25/3 25
+Ethernet100 245,246 Ethernet26/1 26
+Ethernet102 247,248 Ethernet26/3 26
+Ethernet104 149,150 Ethernet27/1 27
+Ethernet106 151,152 Ethernet27/3 27
+Ethernet108 153,154 Ethernet28/1 28
+Ethernet110 155,156 Ethernet28/3 28
+Ethernet112 173,174 Ethernet29/1 29
+Ethernet114 175,176 Ethernet29/3 29
+Ethernet116 161,162 Ethernet30/1 30
+Ethernet118 163,164 Ethernet30/3 30
+Ethernet120 181,182 Ethernet31/1 31
+Ethernet122 183,184 Ethernet31/3 31
+Ethernet124 185,186 Ethernet32/1 32
+Ethernet126 187,188 Ethernet32/3 32
+Ethernet128 69,70 Ethernet33/1 33
+Ethernet130 71,72 Ethernet33/3 33
+Ethernet132 73,74 Ethernet34/1 34
+Ethernet134 75,76 Ethernet34/3 34
+Ethernet136 93,94 Ethernet35/1 35
+Ethernet138 95,96 Ethernet35/3 35
+Ethernet140 81,82 Ethernet36/1 36
+Ethernet142 83,84 Ethernet36/3 36
+Ethernet144 101,102 Ethernet37/1 37
+Ethernet146 103,104 Ethernet37/3 37
+Ethernet148 105,106 Ethernet38/1 38
+Ethernet150 107,108 Ethernet38/3 38
+Ethernet152 9,10 Ethernet39/1 39
+Ethernet154 11,12 Ethernet39/3 39
+Ethernet156 1,2 Ethernet40/1 40
+Ethernet158 3,4 Ethernet40/3 40
+Ethernet160 17,18 Ethernet41/1 41
+Ethernet162 19,20 Ethernet41/3 41
+Ethernet164 29,30 Ethernet42/1 42
+Ethernet166 31,32 Ethernet42/3 42
+Ethernet168 41,42 Ethernet43/1 43
+Ethernet170 43,44 Ethernet43/3 43
+Ethernet172 33,34 Ethernet44/1 44
+Ethernet174 35,36 Ethernet44/3 44
+Ethernet176 49,50,51,52 Ethernet45/1 45
+Ethernet180 61,62,63,64 Ethernet46/1 46
+Ethernet184 125,126,127,128 Ethernet47/1 47
+Ethernet188 113,114,115,116 Ethernet48/1 48
+Ethernet192 129,130,131,132 Ethernet49/1 49
+Ethernet196 137,138,139,140 Ethernet50/1 50
+Ethernet200 201,202,203,204 Ethernet51/1 51
+Ethernet204 193,194,195,196 Ethernet52/1 52
+Ethernet208 209,210 Ethernet53/1 53
+Ethernet210 211,212 Ethernet53/3 53
+Ethernet212 221,222 Ethernet54/1 54
+Ethernet214 223,224 Ethernet54/3 54
+Ethernet216 233,234 Ethernet55/1 55
+Ethernet218 235,236 Ethernet55/3 55
+Ethernet220 225,226 Ethernet56/1 56
+Ethernet222 227,228 Ethernet56/3 56
+Ethernet224 241,242 Ethernet57/1 57
+Ethernet226 243,244 Ethernet57/3 57
+Ethernet228 253,254 Ethernet58/1 58
+Ethernet230 255,256 Ethernet58/3 58
+Ethernet232 157,158 Ethernet59/1 59
+Ethernet234 159,160 Ethernet59/3 59
+Ethernet236 145,146 Ethernet60/1 60
+Ethernet238 147,148 Ethernet60/3 60
+Ethernet240 165,166 Ethernet61/1 61
+Ethernet242 167,168 Ethernet61/3 61
+Ethernet244 169,170 Ethernet62/1 62
+Ethernet246 171,172 Ethernet62/3 62
+Ethernet248 189,190 Ethernet63/1 63
+Ethernet250 191,192 Ethernet63/3 63
+Ethernet252 177,178 Ethernet64/1 64
+Ethernet254 179,180 Ethernet64/3 64
+Ethernet256 257 Ethernet65 65
+Ethernet260 259 Ethernet66 66
diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py
old mode 100644
new mode 100755
index f3943e734b58..7ff632e152b9
--- a/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py
+++ b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py
@@ -1,25 +1,58 @@
#!/usr/bin/env python
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
try:
- from sonic_sfp.sfputilbase import sfputilbase
-except ImportError, e:
- raise ImportError (str(e) + "- required module not found")
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
-class sfputil(sfputilbase):
- """Platform specific sfputil class"""
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
- port_start = 0
- port_end = 31
- ports_in_block = 32
+ PORT_START = 0
+ PORT_END = 31
+ PORTS_IN_BLOCK = 32
- port_to_eeprom_mapping = {}
+ _port_to_eeprom_mapping = {}
+ qsfp_ports = range(0, PORTS_IN_BLOCK + 1)
- _qsfp_ports = range(0, ports_in_block + 1)
+ @property
+ def port_start(self):
+ return self.PORT_START
- def __init__(self, port_num):
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(0, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
# Override port_to_eeprom_mapping for class initialization
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
- for x in range(self.port_start, self.port_end + 1):
+
+ for x in range(self.PORT_START, self.PORT_END + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format( x + 26 )
- sfputilbase.__init__(self, port_num)
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+ raise NotImplementedError
+
+ def get_low_power_mode(self, port_num):
+ raise NotImplementedError
+
+ def set_low_power_mode(self, port_num, lpmode):
+ raise NotImplementedError
+
+ def reset(self, port_num):
+ raise NotImplementedError
+
diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1
new file mode 120000
index 000000000000..36b1b840b83e
--- /dev/null
+++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1
@@ -0,0 +1 @@
+Force10-S6100
\ No newline at end of file
diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py
index 534e587ae722..d6fbcbcf6944 100644
--- a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py
+++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py
@@ -1,27 +1,433 @@
-#!/usr/bin/env python
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+# +-i2c----+--------+
+# | 6 | 7 |
+# | +-------------+ |
+# | |IOM1 | IOM3 | |
+# | |IOM2 | IOM4 | |
+# | +-------------+ |
+# | 8 | 9 |
+# +--------+--------+
+
try:
- from sonic_sfp.sfputilbase import sfputilbase
-except ImportError, e:
- raise ImportError (str(e) + "- required module not found")
+ import time
+ import os
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 0
+ PORT_END = 63
+ PORTS_IN_BLOCK = 64
+
+ _port_to_eeprom_mapping = {}
+ _port_to_i2c_mapping = {
+ 0: [6, 18, 34, 50, 66],
+ 1: [6, 19, 35, 51, 67],
+ 2: [6, 20, 36, 52, 68],
+ 3: [6, 21, 37, 53, 69],
+ 4: [6, 22, 38, 54, 70],
+ 5: [6, 23, 39, 55, 71],
+ 6: [6, 24, 40, 56, 72],
+ 7: [6, 25, 41, 57, 73],
+ 8: [6, 26, 42, 58, 74],
+ 9: [6, 27, 43, 59, 75],
+ 10: [6, 28, 44, 60, 76],
+ 11: [6, 29, 45, 61, 77],
+ 12: [6, 30, 46, 62, 78],
+ 13: [6, 31, 47, 63, 79],
+ 14: [6, 32, 48, 64, 80],
+ 15: [6, 33, 49, 65, 81],
+ 16: [8, 18, 34, 50, 66],
+ 17: [8, 19, 35, 51, 67],
+ 18: [8, 20, 36, 52, 68],
+ 19: [8, 21, 37, 53, 69],
+ 20: [8, 22, 38, 54, 70],
+ 21: [8, 23, 39, 55, 71],
+ 22: [8, 24, 40, 56, 72],
+ 23: [8, 25, 41, 57, 73],
+ 24: [8, 26, 42, 58, 74],
+ 25: [8, 27, 43, 59, 75],
+ 26: [8, 28, 44, 60, 76],
+ 27: [8, 29, 45, 61, 77],
+ 28: [8, 30, 46, 62, 78],
+ 29: [8, 31, 47, 63, 79],
+ 30: [8, 32, 48, 64, 80],
+ 31: [8, 33, 49, 65, 81],
+ 32: [7, 18, 34, 50, 66],
+ 33: [7, 19, 35, 51, 67],
+ 34: [7, 20, 36, 52, 68],
+ 35: [7, 21, 37, 53, 69],
+ 36: [7, 22, 38, 54, 70],
+ 37: [7, 23, 39, 55, 71],
+ 38: [7, 24, 40, 56, 72],
+ 39: [7, 25, 41, 57, 73],
+ 40: [7, 26, 42, 58, 74],
+ 41: [7, 27, 43, 59, 75],
+ 42: [7, 28, 44, 60, 76],
+ 43: [7, 29, 45, 61, 77],
+ 44: [7, 30, 46, 62, 78],
+ 45: [7, 31, 47, 63, 79],
+ 46: [7, 32, 48, 64, 80],
+ 47: [7, 33, 49, 65, 81],
+ 48: [9, 18, 34, 50, 66],
+ 49: [9, 19, 35, 51, 67],
+ 50: [9, 20, 36, 52, 68],
+ 51: [9, 21, 37, 53, 69],
+ 52: [9, 22, 38, 54, 70],
+ 53: [9, 23, 39, 55, 71],
+ 54: [9, 24, 40, 56, 72],
+ 55: [9, 25, 41, 57, 73],
+ 56: [9, 26, 42, 58, 74],
+ 57: [9, 27, 43, 59, 75],
+ 58: [9, 28, 44, 60, 76],
+ 59: [9, 29, 45, 61, 77],
+ 60: [9, 30, 46, 62, 78],
+ 61: [9, 31, 47, 63, 79],
+ 62: [9, 32, 48, 64, 80],
+ 63: [9, 33, 49, 65, 81]
+}
+
+ IOM_1_PORT_START = 0
+ IOM_1_PORT_END = 15
+
+ IOM_2_PORT_START = 16
+ IOM_2_PORT_END = 31
+
+ IOM_3_PORT_START = 32
+ IOM_3_PORT_END = 47
+
+ IOM_4_PORT_START = 48
+ IOM_4_PORT_END = 63
+
+ BASE_VAL_PATH="/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
+
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(0, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def iom1_port_start(self):
+ return self.IOM_1_PORT_START
+
+ @property
+ def iom1_port_end(self):
+ return self.IOM_1_PORT_END
+
+ @property
+ def iom2_port_start(self):
+ return self.IOM_2_PORT_START
+
+ @property
+ def iom2_port_end(self):
+ return self.IOM_2_PORT_END
+
+ @property
+ def iom3_port_start(self):
+ return self.IOM_3_PORT_START
+
+ @property
+ def iom3_port_end(self):
+ return self.IOM_3_PORT_END
+
+ @property
+ def iom4_port_start(self):
+ return self.IOM_4_PORT_START
+
+ @property
+ def iom4_port_end(self):
+ return self.IOM_4_PORT_END
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ @property
+ def port_to_i2c_mapping(self):
+ return self._port_to_i2c_mapping
+
+
+ def __init__(self):
+ eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
+ global port_to_eeprom_path
+
+ for port_num in range(0, self.port_end + 1):
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ assigned=0
+ #i2c-6
+ for x in range(1,5):
+ port_to_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[port_num][0], self.port_to_i2c_mapping[port_num][x])
+ if ( os.path.isfile(port_to_eeprom_path) ):
+ self.port_to_eeprom_mapping[port_num]=port_to_eeprom_path
+ assigned=1
+ elif (not assigned):
+ self.port_to_eeprom_mapping[port_num]="No IOM"
+
+ elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ assigned=0
+ #i2c-8
+ for x in range(1,5):
+ port_to_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[port_num][0], self.port_to_i2c_mapping[port_num][x])
+ if ( os.path.isfile(port_to_eeprom_path) ):
+ self.port_to_eeprom_mapping[port_num]=port_to_eeprom_path
+ assigned=1
+ elif (not assigned):
+ self.port_to_eeprom_mapping[port_num]="No IOM"
+
+ elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end:
+ assigned=0
+ #i2c-7
+ for x in range(1,5):
+ port_to_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[port_num][0], self.port_to_i2c_mapping[port_num][x])
+ if ( os.path.isfile(port_to_eeprom_path) ):
+ self.port_to_eeprom_mapping[port_num]=port_to_eeprom_path
+ assigned=1
+ elif (not assigned):
+ self.port_to_eeprom_mapping[port_num]="No IOM"
+
+
+ elif port_num >= self.iom4_port_start and port_num <= self.iom4_port_end:
+ assigned=0
+ #i2c-9
+ for x in range(1,5):
+ port_to_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[port_num][0], self.port_to_i2c_mapping[port_num][x])
+ if ( os.path.isfile(port_to_eeprom_path) ):
+ self.port_to_eeprom_mapping[port_num]=port_to_eeprom_path
+ assigned=1
+ elif (not assigned):
+ self.port_to_eeprom_mapping[port_num]="No IOM"
+
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+
+ global i2c_line
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ #port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line=14
+ elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ i2c_line=16
+ elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end:
+ i2c_line=15
+ elif port_num >= self.iom4_port_start and port_num <= self.iom4_port_end:
+ i2c_line=17
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_modprs"
+ reg_file = open(qsfp_path, "r")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ #Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ #Rationalize port settings
+ if port_num > 15:
+ port_num=port_num%16
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # ModPrsL is active low
+ if reg_value & mask == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ #port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line=14
+ elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ i2c_line=16
+ elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end:
+ i2c_line=15
+ elif port_num >= self.iom4_port_start and port_num <= self.iom4_port_end:
+ i2c_line=17
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ #Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ #Rationalize port settings
+ if port_num > 15:
+ port_num=port_num%16
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # LPMode is active high
+ if reg_value & mask == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ #port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line=14
+ elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ i2c_line=16
+ elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end:
+ i2c_line=15
+ elif port_num >= self.iom4_port_start and port_num <= self.iom4_port_end:
+ i2c_line=17
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r+")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ #Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ #Rationalize port settings
+ if port_num > 15:
+ port_num=port_num%16
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # LPMode is active high; set or clear the bit accordingly
+ if lpmode is True:
+ reg_value = reg_value | mask
+ else:
+ reg_value = reg_value & ~mask
+
+ # Convert our register value back to a hex string and write back
+ content = hex(reg_value)
+
+ reg_file.seek(0)
+ reg_file.write(content)
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+
+ global i2c_line
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ #port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line=14
+ elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ i2c_line=16
+ elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end:
+ i2c_line=15
+ elif port_num >= self.iom4_port_start and port_num <= self.iom4_port_end:
+ i2c_line=17
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r+")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ #Absence of IOM throws read error
+ if (content == 'read error'):
+ print("it's empty");
+ return False
+
+ # File content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ #Rationalize port settings
+ if port_num > 15:
+ port_num=port_num%16
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+ # ResetL is active low
+ reg_value = reg_value & ~mask
-class sfputil(sfputilbase):
- """Platform specific sfputil class"""
+ # Convert our register value back to a hex string and write back
+ reg_file.seek(0)
+ reg_file.write(hex(reg_value))
+ reg_file.close()
- port_start = 0
- port_end = 63
- ports_in_block = 64
+ # Sleep 1 second to allow it to settle
+ time.sleep(1)
- eeprom_offset = 18
+ # Flip the bit back high and write back to the register to take port out of reset
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "w")
- port_to_eeprom_mapping = {}
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
- _qsfp_ports = range(0, ports_in_block + 1)
+ reg_value = reg_value | mask
+ reg_file.seek(0)
+ reg_file.write(hex(reg_value))
+ reg_file.close()
- def __init__(self, port_num):
- # Override port_to_eeprom_mapping for class initialization
- eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'
- for x in range(0, self.port_end + 1):
- self.port_to_eeprom_mapping[x] = eeprom_path.format(x + self.eeprom_offset)
- sfputilbase.__init__(self, port_num)
+ return True
diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py
index 07e094db7bb8..5609abe9b49a 100644
--- a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py
+++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py
@@ -1,60 +1,339 @@
-#!/usr/bin/env python
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
try:
- from sonic_sfp.sfputilbase import sfputilbase
-except ImportError, e:
- raise ImportError (str(e) + "- required module not found")
-
-
-class sfputil(sfputilbase):
- """Platform specific sfputil class"""
-
- port_start = 0
- port_end = 31
- ports_in_block = 32
-
- port_to_eeprom_mapping = {}
- port_to_i2c_mapping = {
- 0: 18,
- 1: 19,
- 2: 20,
- 3: 21,
- 4: 22,
- 5: 23,
- 6: 24,
- 7: 25,
- 8: 26,
- 9: 27,
- 10: 28,
- 11: 29,
- 12: 31,
- 13: 30,
- 14: 33,
- 15: 32,
- 16: 34,
- 17: 35,
- 18: 36,
- 19: 37,
- 20: 38,
- 21: 39,
- 22: 40,
- 23: 41,
- 24: 42,
- 25: 43,
- 26: 44,
- 27: 45,
- 28: 46,
- 29: 47,
- 30: 48,
- 31: 49
- }
-
- _qsfp_ports = range(0, ports_in_block + 1)
-
- def __init__(self, port_num):
- # Override port_to_eeprom_mapping for class initialization
- eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'
- for x in range(0, self.port_end + 1):
- port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
- self.port_to_eeprom_mapping[x] = port_eeprom_path
- sfputilbase.__init__(self, port_num)
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 0
+ PORT_END = 31
+ PORTS_IN_BLOCK = 32
+ IOM_1_PORT_START = 0
+ IOM_1_PORT_END = 11
+ IOM_2_PORT_START = 12
+ IOM_2_PORT_END = 21
+ IOM_3_PORT_START = 22
+ IOM_3_PORT_END = 31
+
+ BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
+
+ _port_to_eeprom_mapping = {}
+ _port_to_i2c_mapping = {
+ 0: [9, 18],
+ 1: [9, 19],
+ 2: [9, 20],
+ 3: [9, 21],
+ 4: [9, 22],
+ 5: [9, 23],
+ 6: [9, 24],
+ 7: [9, 25],
+ 8: [8, 26],
+ 9: [8, 27],
+ 10: [8, 28],
+ 11: [8, 29],
+ 12: [8, 31], # reordered
+ 13: [8, 30],
+ 14: [8, 33], # reordered
+ 15: [8, 32],
+ 16: [7, 34],
+ 17: [7, 35],
+ 18: [7, 36],
+ 19: [7, 37],
+ 20: [7, 38],
+ 21: [7, 39],
+ 22: [7, 40],
+ 23: [7, 41],
+ 24: [6, 42],
+ 25: [6, 43],
+ 26: [6, 44],
+ 27: [6, 45],
+ 28: [6, 46],
+ 29: [6, 47],
+ 30: [6, 48],
+ 31: [6, 49]
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(0, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def iom1_port_start(self):
+ return self.IOM_1_PORT_START
+
+ @property
+ def iom1_port_end(self):
+ return self.IOM_1_PORT_END
+
+ @property
+ def iom2_port_start(self):
+ return self.IOM_2_PORT_START
+
+ @property
+ def iom2_port_end(self):
+ return self.IOM_2_PORT_END
+
+ @property
+ def iom3_port_start(self):
+ return self.IOM_3_PORT_START
+
+ @property
+ def iom3_port_end(self):
+ return self.IOM_3_PORT_END
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ @property
+ def port_to_i2c_mapping(self):
+ return self._port_to_i2c_mapping
+
+ def __init__(self):
+ eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
+
+ for x in range(0, self.port_end+1):
+ self.port_to_eeprom_mapping[x] = eeprom_path.format(
+ self.port_to_i2c_mapping[x][0],
+ self.port_to_i2c_mapping[x][1])
+
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+
+ global i2c_line
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ # port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line = 14
+ elif (port_num >= self.iom2_port_start and
+ port_num <= self.iom2_port_end):
+ i2c_line = 15
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ i2c_line = 16
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_modprs"
+ reg_file = open(qsfp_path, "r")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ # Rationalize port settings
+ if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ port_num = port_num % 12
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ port_num = port_num % 22
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # ModPrsL is active low
+ if reg_value & mask == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ # port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line = 14
+ elif (port_num >= self.iom2_port_start and
+ port_num <= self.iom2_port_end):
+ i2c_line = 15
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ i2c_line = 16
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ # Rationalize port settings
+ if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ port_num = port_num % 12
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ port_num = port_num % 22
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # LPMode is active high
+ if reg_value & mask == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ # port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line = 14
+ elif (port_num >= self.iom2_port_start and
+ port_num <= self.iom2_port_end):
+ i2c_line = 15
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ i2c_line = 16
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r+")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # Absence of IOM throws read error
+ if (content == 'read error'):
+ return False
+
+ # content is a string containing the hex representation of the register
+ reg_value = int(content, 16)
+
+ # Rationalize port settings
+ if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ port_num = port_num % 12
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ port_num = port_num % 22
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+ # LPMode is active high; set or clear the bit accordingly
+ if lpmode is True:
+ reg_value = reg_value | mask
+ else:
+ reg_value = reg_value & ~mask
+
+ # Convert our register value back to a hex string and write back
+ content = hex(reg_value)
+
+ reg_file.seek(0)
+ reg_file.write(content)
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ # port_num and i2c match
+ if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end:
+ i2c_line = 14
+ elif (port_num >= self.iom2_port_start and
+ port_num <= self.iom2_port_end):
+ i2c_line = 15
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ i2c_line = 16
+
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "r+")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # File content is a string containing the hex representation of th
+ reg_value = int(content, 16)
+
+ # Rationalize port settings
+ if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end:
+ port_num = port_num % 12
+ elif (port_num >= self.iom3_port_start and
+ port_num <= self.iom3_port_end):
+ port_num = port_num % 22
+
+ # Mask off the bit corresponding to our port
+ mask = (1 << port_num)
+
+ # ResetL is active low
+ reg_value = reg_value & ~mask
+
+ # Convert our register value back to a hex string and write back
+ reg_file.seek(0)
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ # Sleep 1 second to allow it to settle
+ time.sleep(1)
+
+ # Flip the bit back high and write back to the register to take
+ # port out of reset
+ try:
+ qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode"
+ reg_file = open(qsfp_path, "w+")
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = reg_value | mask
+ reg_file.seek(0)
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py
index ad70e584bb2a..de5c24ba0e6d 100644
--- a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py
@@ -18,5 +18,5 @@
class board(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, name, path, cpld_root, ro):
- self.eeprom_path = "/tmp/eeprom"
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py
index 020faab9db58..645c76b9f0db 100644
--- a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py
@@ -1,19 +1,23 @@
-#!/usr/bin/env python
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
try:
- from sonic_sfp.sfputilbase import sfputilbase
-except ImportError, e:
- raise ImportError (str(e) + "- required module not found")
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
-class sfputil(sfputilbase):
- """Platform specific sfputil class"""
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
- port_start = 0
- port_end = 31
- ports_in_block = 32
+ PORT_START = 0
+ PORT_END = 31
+ PORTS_IN_BLOCK = 32
- port_to_eeprom_mapping = {}
+ _port_to_eeprom_mapping = {}
port_to_i2c_mapping = {
0: 22,
1: 23,
@@ -49,12 +53,117 @@ class sfputil(sfputilbase):
31: 21
}
- _qsfp_ports = range(0, ports_in_block + 1)
+ @property
+ def port_start(self):
+ return self.PORT_START
- def __init__(self, port_num):
- # Override port_to_eeprom_mapping for class initialization
- eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'
- for x in range(self.port_start, self.port_end + 1):
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(0, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
+
+ for x in range(0, self.port_end + 1):
port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
self.port_to_eeprom_mapping[x] = port_eeprom_path
- sfputilbase.__init__(self, port_num)
+ SfpUtilBase.__init__(self)
+
+ 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
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/present")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ # LPMode is active high; set or clear the bit accordingly
+ if lpmode is True:
+ reg_value = 1
+ else:
+ reg_value = 0
+
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset"
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 0
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ # Sleep 2 second to allow it to settle
+ time.sleep(2)
+
+ # Flip the value back write back to the register to take port out of reset
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 1
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini
new file mode 100644
index 000000000000..a8eaeb1f0665
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini
@@ -0,0 +1,56 @@
+# 48x25G + 6x100G
+# name lanes alias
+Ethernet0 2 Ethernet0
+Ethernet4 1 Ethernet4
+Ethernet8 4 Ethernet8
+Ethernet12 3 Ethernet12
+Ethernet16 6 Ethernet16
+Ethernet20 5 Ethernet20
+Ethernet24 8 Ethernet24
+Ethernet28 7 Ethernet28
+Ethernet32 10 Ethernet32
+Ethernet36 9 Ethernet36
+Ethernet40 12 Ethernet40
+Ethernet44 11 Ethernet44
+Ethernet48 22 Ethernet48
+Ethernet52 21 Ethernet52
+Ethernet56 24 Ethernet56
+Ethernet60 23 Ethernet60
+Ethernet64 34 Ethernet64
+Ethernet68 33 Ethernet68
+Ethernet72 36 Ethernet72
+Ethernet76 35 Ethernet76
+Ethernet80 38 Ethernet80
+Ethernet84 37 Ethernet84
+Ethernet88 40 Ethernet88
+Ethernet92 39 Ethernet92
+Ethernet96 42 Ethernet96
+Ethernet100 41 Ethernet100
+Ethernet104 44 Ethernet104
+Ethernet108 43 Ethernet108
+Ethernet112 50 Ethernet112
+Ethernet116 49 Ethernet116
+Ethernet120 52 Ethernet120
+Ethernet124 51 Ethernet124
+Ethernet128 54 Ethernet128
+Ethernet132 53 Ethernet132
+Ethernet136 56 Ethernet136
+Ethernet140 55 Ethernet140
+Ethernet144 66 Ethernet144
+Ethernet148 65 Ethernet148
+Ethernet152 68 Ethernet152
+Ethernet156 67 Ethernet156
+Ethernet160 70 Ethernet160
+Ethernet164 69 Ethernet164
+Ethernet168 72 Ethernet168
+Ethernet172 71 Ethernet172
+Ethernet176 82 Ethernet176
+Ethernet180 81 Ethernet180
+Ethernet184 84 Ethernet184
+Ethernet188 83 Ethernet188
+Ethernet192 85,86,87,88 Ethernet192
+Ethernet196 97,98,99,100 Ethernet196
+Ethernet200 105,106,107,108 Ethernet200
+Ethernet204 101,102,103,104 Ethernet204
+Ethernet208 117,118,119,120 Ethernet208
+Ethernet212 109,110,111,112 Ethernet212
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile
new file mode 100644
index 000000000000..6f60cbd6118c
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/etc/bcm/th-d7054q28b-48x10g-6x100g.config.bcm
+SAI_NUM_ECMP_MEMBERS=32
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf
new file mode 100644
index 000000000000..1db64ba02c38
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
+VAR_LOG_SIZE=1024
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml b/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml
new file mode 100644
index 000000000000..0e579ccbde14
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+ OCPSCH0104001MS
+ 10.10.1.26
+ SONiC-Inventec-d7054
+ 10.10.1.25
+ 1
+ 10
+ 3
+
+
+ OCPSCH0104002MS
+ 10.10.2.26
+ SONiC-Inventec-d7054
+ 10.10.2.25
+ 1
+ 10
+ 3
+
+
+
+
+ 64536
+ SONiC-Inventec-d7054
+
+
+ 10.10.1.26
+
+
+
+
+ 10.10.2.26
+
+
+
+
+
+
+
+ 64542
+ OCPSCH0104001MS
+
+
+
+ 64543
+ OCPSCH0104002MS
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 100.0.0.9/32
+
+ 100.0.0.9/32
+
+
+
+
+
+
+
+ SONiC-Inventec-d7054
+
+
+
+
+
+ Ethernet0
+ 10.10.1.25/30
+
+
+
+ Ethernet4
+ 10.10.2.25/30
+
+
+
+
+
+
+
+
+
+
+
+ 40000
+ DeviceInterfaceLink
+ OCPSCH0104001MS
+ Ethernet24
+ SONiC-Inventec-d7054
+ Ethernet0
+
+
+ 40000
+ DeviceInterfaceLink
+ OCPSCH0104002MS
+ Ethernet24
+ SONiC-Inventec-d7054
+ Ethernet4
+
+
+
+
+ SONiC-Inventec-d7054
+ INVENTEC-D7054Q28B-S48-Q6
+
+
+
+
+
+
+ SONiC-Inventec-d7054
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ SONiC-Inventec-d7054
+ INVENTEC-D7054Q28B-S48-Q6
+
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..de5c24ba0e6d
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Inventec d7032q28b
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..c2edefd2eb70
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py
@@ -0,0 +1,209 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 0
+ PORT_END = 53
+ PORTS_IN_BLOCK = 54
+ QSFP_PORT_START = 48
+ QSFP_PORT_END = 53
+
+ _port_to_eeprom_mapping = {}
+ port_to_i2c_mapping = {
+ 0: 11,
+ 1: 10,
+ 2: 13,
+ 3: 12,
+ 4: 15,
+ 5: 14,
+ 6: 17,
+ 7: 16,
+ 8: 19,
+ 9: 18,
+ 10: 21,
+ 11: 20,
+ 12: 23,
+ 13: 22,
+ 14: 25,
+ 15: 24,
+ 16: 27,
+ 17: 26,
+ 18: 29,
+ 19: 28,
+ 20: 31,
+ 21: 30,
+ 22: 33,
+ 23: 32,
+ 24: 35,
+ 25: 34,
+ 26: 37,
+ 27: 36,
+ 28: 39,
+ 29: 38,
+ 30: 41,
+ 31: 40,
+ 32: 43,
+ 33: 42,
+ 34: 45,
+ 35: 44,
+ 36: 47,
+ 37: 46,
+ 38: 49,
+ 39: 48,
+ 40: 51,
+ 41: 50,
+ 42: 53,
+ 43: 52,
+ 44: 55,
+ 45: 54,
+ 46: 57,
+ 47: 56,
+ 48: 59,
+ 49: 58,
+ 50: 61,
+ 51: 60,
+ 52: 63,
+ 53: 62
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_port_start(self):
+ return self.QSFP_PORT_START
+
+ @property
+ def qsfp_port_end(self):
+ return self.QSFP_PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom"
+
+ for x in range(0, self.port_end + 1):
+ port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
+ self.port_to_eeprom_mapping[x] = port_eeprom_path
+ SfpUtilBase.__init__(self)
+
+ 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
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/present")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ print "\nError:SFP's don't support this property"
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ # LPMode is active high; set or clear the bit accordingly
+ if lpmode is True:
+ reg_value = 1
+ else:
+ reg_value = 0
+
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset"
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ print "\nError:SFP's don't support this property"
+ return False
+
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 0
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ # Sleep 2 second to allow it to settle
+ time.sleep(2)
+
+ # Flip the value back write back to the register to take port out of reset
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 1
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py
index db71cb423503..0d7870b785fa 100644
--- a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py
+++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py
@@ -46,8 +46,23 @@ def __init__(self):
SfpUtilBase.__init__(self)
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
- raise NotImplementedError
+ try:
+ reg_file = open("/bsp/qsfp/qsfp%d_status" % (port_num+1))
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # content is a string with the qsfp status
+ if content == "good":
+ return True
+
+ return False
def get_low_power_mode(self, port_num):
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
index b746af219917..b768cc44022d 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
@@ -46,8 +46,23 @@ def __init__(self):
SfpUtilBase.__init__(self)
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
- raise NotImplementedError
+ try:
+ reg_file = open("/bsp/qsfp/qsfp%d_status" % (port_num+1))
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # content is a string with the qsfp status
+ if content == "good":
+ return True
+
+ return False
def get_low_power_mode(self, port_num):
diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py
index b746af219917..b768cc44022d 100644
--- a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py
+++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py
@@ -46,8 +46,23 @@ def __init__(self):
SfpUtilBase.__init__(self)
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
- raise NotImplementedError
+ try:
+ reg_file = open("/bsp/qsfp/qsfp%d_status" % (port_num+1))
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = reg_file.readline().rstrip()
+
+ # content is a string with the qsfp status
+ if content == "good":
+ return True
+
+ return False
def get_low_power_mode(self, port_num):
diff --git a/dockers/docker-dhcp-relay/Dockerfile.j2 b/dockers/docker-dhcp-relay/Dockerfile.j2
index 3c6614c4921f..2c2bdcaecbf7 100644
--- a/dockers/docker-dhcp-relay/Dockerfile.j2
+++ b/dockers/docker-dhcp-relay/Dockerfile.j2
@@ -22,9 +22,7 @@ RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
RUN rm -rf /debs
-COPY ["start.sh", "isc-dhcp-relay.sh", "/usr/bin/"]
-COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
-COPY ["isc-dhcp-relay.j2", "/usr/share/sonic/templates/"]
-COPY ["wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
+COPY ["docker_init.sh", "start.sh", "/usr/bin/"]
+COPY ["docker-dhcp-relay.supervisord.conf.j2", "wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
-ENTRYPOINT ["/usr/bin/supervisord"]
+ENTRYPOINT ["/usr/bin/docker_init.sh"]
diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2
new file mode 100644
index 000000000000..747f65a3aaf6
--- /dev/null
+++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2
@@ -0,0 +1,67 @@
+[supervisord]
+logfile_maxbytes=1MB
+logfile_backups=2
+nodaemon=true
+
+[program:start.sh]
+command=/usr/bin/start.sh
+priority=1
+autostart=true
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:rsyslogd]
+command=/usr/sbin/rsyslogd -n
+priority=2
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+{# If our configuration has VLANs... #}
+{% if VLAN %}
+{# Count how many VLANs require a DHCP relay agent... #}
+{% set num_relays = { 'count': 0 } %}
+{% for vlan_name in VLAN %}
+{% if VLAN[vlan_name]['dhcp_servers'] %}
+{% set _dummy = num_relays.update({'count': num_relays.count + 1}) %}
+{% endif %}
+{% endfor %}
+{# If one or more of the VLANs require a DHCP relay agent... #}
+{% if num_relays.count > 0 %}
+[group:isc-dhcp-relay]
+programs=
+{%- set add_preceding_comma = { 'flag': False } -%}
+{%- for vlan_name in VLAN -%}
+{%- if VLAN[vlan_name]['dhcp_servers'] -%}
+{%- if add_preceding_comma.flag %},{% endif -%}
+{%- set _dummy = add_preceding_comma.update({'flag': True}) -%}
+isc-dhcp-relay-{{ vlan_name }}
+{%- endif %}
+{% endfor %}
+
+
+{# Create a program entry for each DHCP relay agent instance #}
+{% for vlan_name in VLAN -%}
+{%- if VLAN[vlan_name]['dhcp_servers'] -%}
+[program:isc-dhcp-relay-{{ vlan_name }}]
+command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -i {{ vlan_name }}
+{%- for (name, prefix) in INTERFACE -%}
+{%- if prefix | ipv4 %} -i {{ name }}{% endif -%}
+{%- endfor -%}
+{%- for (name, prefix) in PORTCHANNEL_INTERFACE -%}
+{%- if prefix | ipv4 %} -i {{ name }}{% endif -%}
+{%- endfor -%}
+{%- for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %}
+
+priority=3
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
diff --git a/dockers/docker-dhcp-relay/docker_init.sh b/dockers/docker-dhcp-relay/docker_init.sh
new file mode 100755
index 000000000000..f6d402e6f780
--- /dev/null
+++ b/dockers/docker-dhcp-relay/docker_init.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+# Generate supervisord config file
+mkdir -p /etc/supervisor/conf.d/
+sonic-cfggen -d -t /usr/share/sonic/templates/docker-dhcp-relay.supervisord.conf.j2 > /etc/supervisor/conf.d/docker-dhcp-relay.supervisord.conf
+
+# Generate the script that waits for all interfaces to come up and make it executable
+sonic-cfggen -d -t /usr/share/sonic/templates/wait_for_intf.sh.j2 > /usr/bin/wait_for_intf.sh
+chmod +x /usr/bin/wait_for_intf.sh
+
+# Generate port name-alias map for isc-dhcp-relay to parse. Each line contains one
+# name-alias pair of the form " "
+sonic-cfggen -d --var-json "PORT" | python -c "import sys, json, os; [sys.stdout.write('%s %s\n' % (k, v['alias'] if 'alias' in v else k)) for (k, v) in json.load(sys.stdin).iteritems()]" > /tmp/port-name-alias-map.txt
+
+# The docker container should start this script as PID 1, so now that supervisord is
+# properly configured, we exec supervisord so that it runs as PID 1 for the
+# duration of the container's lifetime
+exec /usr/bin/supervisord
diff --git a/dockers/docker-dhcp-relay/isc-dhcp-relay.j2 b/dockers/docker-dhcp-relay/isc-dhcp-relay.j2
deleted file mode 100644
index cdedfcf9692b..000000000000
--- a/dockers/docker-dhcp-relay/isc-dhcp-relay.j2
+++ /dev/null
@@ -1,28 +0,0 @@
-SERVERS="{{ DHCP_SERVER | join(' ') }}"
-
-INTERFACES="
-{%- set add_preceding_space = { 'flag': False } %}
-{%- for (name, prefix) in INTERFACE %}
-{%- if prefix | ipv4 %}
-{%- if add_preceding_space.flag %} {% endif %}
-{{ name }}
-{%- set _dummy = add_preceding_space.update({'flag': True}) %}
-{%- endif %}
-{%- endfor %}
-{%- for (name, prefix) in VLAN_INTERFACE %}
-{%- if prefix | ipv4 %}
-{%- if add_preceding_space.flag %} {% endif %}
-{{ name }}
-{%- set _dummy = add_preceding_space.update({'flag': True}) %}
-{%- endif %}
-{%- endfor %}
-{%- for (name, prefix) in PORTCHANNEL_INTERFACE %}
-{%- if prefix | ipv4 %}
-{%- if add_preceding_space.flag %} {% endif %}
-{{ name }}
-{%- set _dummy = add_preceding_space.update({'flag': True}) %}
-{%- endif %}
-{%- endfor %}"
-
-# '-a' option provides option 82 circuit_id and remote_id information
-OPTIONS="-a %h:%p %P"
diff --git a/dockers/docker-dhcp-relay/isc-dhcp-relay.sh b/dockers/docker-dhcp-relay/isc-dhcp-relay.sh
deleted file mode 100755
index 2224b8a0fe00..000000000000
--- a/dockers/docker-dhcp-relay/isc-dhcp-relay.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-#
-# Based off /etc/init.d/isc-dhcp-relay
-#
-
-# Read init script configuration (interfaces the daemon should listen on
-# and the DHCP server we should forward requests to.)
-[ -f /etc/default/isc-dhcp-relay ] && . /etc/default/isc-dhcp-relay
-
-# Build command line for interfaces (will be passed to dhrelay below.)
-IFCMD=""
-if test "$INTERFACES" != ""; then
- for I in $INTERFACES; do
- IFCMD=${IFCMD}"-i "${I}" "
- done
-fi
-
-exec /usr/sbin/dhcrelay -d -q ${OPTIONS} ${IFCMD} ${SERVERS}
diff --git a/dockers/docker-dhcp-relay/start.sh b/dockers/docker-dhcp-relay/start.sh
index 37c3f488a5c7..b53d7e4e238a 100755
--- a/dockers/docker-dhcp-relay/start.sh
+++ b/dockers/docker-dhcp-relay/start.sh
@@ -1,16 +1,13 @@
#!/usr/bin/env bash
-# Create isc-dhcp-relay config file
-sonic-cfggen -d -t /usr/share/sonic/templates/isc-dhcp-relay.j2 > /etc/default/isc-dhcp-relay
-
+# Remove stale rsyslog PID file if it exists
rm -f /var/run/rsyslogd.pid
+# Start rsyslog
supervisorctl start rsyslogd
-# Wait for all interfaces to come up before starting the DHCP relay
-sonic-cfggen -d -t /usr/share/sonic/templates/wait_for_intf.sh.j2 > /usr/bin/wait_for_intf.sh
-chmod +x /usr/bin/wait_for_intf.sh
+# Wait for all interfaces to come up before starting the DHCP relay agent(s)
/usr/bin/wait_for_intf.sh
-# Start the DHCP relay
-supervisorctl start isc-dhcp-relay
+# Start the DHCP relay agent(s)
+supervisorctl start isc-dhcp-relay:*
diff --git a/dockers/docker-dhcp-relay/supervisord.conf b/dockers/docker-dhcp-relay/supervisord.conf
deleted file mode 100644
index ed1f75d1aed6..000000000000
--- a/dockers/docker-dhcp-relay/supervisord.conf
+++ /dev/null
@@ -1,28 +0,0 @@
-[supervisord]
-logfile_maxbytes=1MB
-logfile_backups=2
-nodaemon=true
-
-[program:start.sh]
-command=/usr/bin/start.sh
-priority=1
-autostart=true
-autorestart=false
-stdout_logfile=syslog
-stderr_logfile=syslog
-
-[program:rsyslogd]
-command=/usr/sbin/rsyslogd -n
-priority=2
-autostart=false
-autorestart=false
-stdout_logfile=syslog
-stderr_logfile=syslog
-
-[program:isc-dhcp-relay]
-command=/usr/bin/isc-dhcp-relay.sh
-priority=3
-autostart=false
-autorestart=false
-stdout_logfile=syslog
-stderr_logfile=syslog
diff --git a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
old mode 100755
new mode 100644
index b859a43b07b1..1524b3221312
--- a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
+++ b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
@@ -25,4 +25,3 @@ wait_until_iface_exists {{ name }}
{% for (name, prefix) in PORTCHANNEL_INTERFACE %}
wait_until_iface_exists {{ name }}
{% endfor %}
-
diff --git a/dockers/docker-fpm-frr/bgpd.conf.j2 b/dockers/docker-fpm-frr/bgpd.conf.j2
index 5452a976368a..07e2dd0c571e 100644
--- a/dockers/docker-fpm-frr/bgpd.conf.j2
+++ b/dockers/docker-fpm-frr/bgpd.conf.j2
@@ -51,6 +51,7 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
{% if bgp_session['asn'] | int != 0 %}
neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }}
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
+ neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }}
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
neighbor {{ neighbor_addr }} allowas-in 1
{% endif %}
@@ -59,6 +60,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
neighbor {{ neighbor_addr }} activate
{% if bgp_session['rrclient'] | int != 0 %}
neighbor {{ neighbor_addr }} route-reflector-client
+{% endif %}
+{% if bgp_session['nhopself'] | int != 0 %}
+ neighbor {{ neighbor_addr }} next-hop-self
{% endif %}
maximum-paths 64
exit-address-family
@@ -68,6 +72,12 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
neighbor {{ neighbor_addr }} activate
{% if bgp_session['rrclient'] | int != 0 %}
neighbor {{ neighbor_addr }} route-reflector-client
+{% endif %}
+{% if bgp_session['nhopself'] | int != 0 %}
+ neighbor {{ neighbor_addr }} next-hop-self
+{% endif %}
+{% if bgp_session['asn'] != DEVICE_METADATA['localhost']['bgp_asn'] %}
+ neighbor {{ neighbor_addr }} route-map set-next-hop-global-v6 in
{% endif %}
maximum-paths 64
exit-address-family
@@ -81,3 +91,6 @@ maximum-paths 64
route-map ISOLATE permit 10
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
!
+route-map set-next-hop-global-v6 permit 10
+set ipv6 next-hop prefer-global
+!
diff --git a/dockers/docker-fpm-quagga/bgpd.conf.j2 b/dockers/docker-fpm-quagga/bgpd.conf.j2
index 0ef144016246..bd8de7e4ba15 100644
--- a/dockers/docker-fpm-quagga/bgpd.conf.j2
+++ b/dockers/docker-fpm-quagga/bgpd.conf.j2
@@ -32,18 +32,17 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
bgp graceful-restart
{% endif %}
{% for (name, prefix) in LOOPBACK_INTERFACE %}
-{# TODO: use v4 lo for backward compatibility, will revisit the case with multiple lo interfaces #}
-{% if prefix | ipv4 %}
+{% if prefix | ipv4 and name == 'Loopback0' %}
bgp router-id {{ prefix | ip }}
{% endif %}
{% endfor %}
{# advertise loopback #}
{% for (name, prefix) in LOOPBACK_INTERFACE %}
-{% if prefix | ipv4 %}
+{% if prefix | ipv4 and name == 'Loopback0' %}
network {{ prefix | ip }}/32
-{% elif prefix | ipv6 %}
+{% elif prefix | ipv6 and name == 'Loopback0' %}
address-family ipv6
- network {{ prefix | ip }}/128
+ network {{ prefix | ip }}/64
exit-address-family
{% endif %}
{% endfor %}
@@ -97,7 +96,11 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
neighbor {{ bgp_peer['name'] }} remote-as {{ deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']] }}
neighbor {{ bgp_peer['name'] }} ebgp-multihop 255
neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound
- neighbor {{ bgp_peer['name'] }} update-source Loopback0
+{% for (name, prefix) in LOOPBACK_INTERFACE %}
+{% if name == 'Loopback1' %}
+ neighbor {{ bgp_peer['name'] }} update-source {{ prefix | ip }}
+{% endif %}
+{% endfor %}
neighbor {{ bgp_peer['name'] }} route-map FROM_BGP_SPEAKER_V4 in
neighbor {{ bgp_peer['name'] }} route-map TO_BGP_SPEAKER_V4 out
{% for ip_range in bgp_peer['ip_range'] %}
diff --git a/dockers/docker-lldp-sv2/Dockerfile.j2 b/dockers/docker-lldp-sv2/Dockerfile.j2
index 158d5b52ffe7..bfb1f9ca678a 100644
--- a/dockers/docker-lldp-sv2/Dockerfile.j2
+++ b/dockers/docker-lldp-sv2/Dockerfile.j2
@@ -30,7 +30,7 @@ RUN pip install /python-wheels/swsssdk-2.0.1-py2-none-any.whl && \
COPY ["start.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
-COPY ["reconfigure.sh", "/opt/"]
+COPY ["reconfigure.sh", "/usr/bin/"]
COPY ["lldpd.conf.j2", "/usr/share/sonic/templates/"]
COPY ["lldpd", "/etc/default/"]
diff --git a/dockers/docker-lldp-sv2/reconfigure.sh b/dockers/docker-lldp-sv2/reconfigure.sh
index 9f42a33a24b4..515e771aa6f2 100755
--- a/dockers/docker-lldp-sv2/reconfigure.sh
+++ b/dockers/docker-lldp-sv2/reconfigure.sh
@@ -2,9 +2,8 @@
set -e
-num_of_interfaces=32
-if_step=4
-last_if_idx=$((num_of_interfaces*if_step - if_step))
+# TODO: Listen to state database when it is ready
+interfaces=$(sonic-cfggen -d -v "PORT.keys() | join(' ')")
function wait_until_if_exists
{
@@ -31,23 +30,23 @@ function wait_until_if_not_exists
while /bin/true ;
do
# wait until all interfaces are created
- echo Wait until all ifaces are created
- for i in $(seq 0 $if_step $last_if_idx)
+ echo Wait until all interfaces are created
+ for i in $interfaces
do
- wait_until_if_exists "Ethernet$i"
+ wait_until_if_exists $i
done
echo Wait 10 seconds while lldpd finds new interfaces
sleep 10
# apply lldpd configuration
- echo apply lldpd configuration
+ echo Apply lldpd configuration
lldpcli -c /etc/lldpd.conf
# wait until all interfaces are destroyed
echo Wait until all ifaces are destroyed
- for i in $(seq 0 $if_step $last_if_idx)
+ for i in $interfaces
do
- wait_until_if_not_exists "Ethernet$i"
+ wait_until_if_not_exists $i
done
done
diff --git a/dockers/docker-lldp-sv2/supervisord.conf b/dockers/docker-lldp-sv2/supervisord.conf
index 505b72d18227..ab62d9ed2e87 100644
--- a/dockers/docker-lldp-sv2/supervisord.conf
+++ b/dockers/docker-lldp-sv2/supervisord.conf
@@ -33,7 +33,7 @@ stdout_logfile=syslog
stderr_logfile=syslog
[program:lldpd-conf-reload]
-command=/opt/reconfigure.sh
+command=/usr/bin/reconfigure.sh
priority=150
autostart=false
autorestart=false
diff --git a/dockers/docker-lldp/Dockerfile b/dockers/docker-lldp/Dockerfile
deleted file mode 100644
index 595c41bcd85e..000000000000
--- a/dockers/docker-lldp/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-FROM docker-base
-
-COPY deps/swsssdk*.whl deps/lldpsyncd_*.deb deps/lldpd_*.deb /deps/
-
-# Make apt-get non-interactive
-ENV DEBIAN_FRONTEND=noninteractive
-
-# Pre-install the fundamental packages
-# Install Python SwSS SDK (lldpsyncd dependency)
-# Install LLDP Sync Daemon
-# Note: dpkg_apt function has the benefit to detect missing .deb file
-# Clean up
-RUN apt-get update && \
- dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } && \
- dpkg_apt /deps/lldpd_*.deb && \
- dpkg_apt /deps/lldpsyncd_*.deb && \
- apt-get install -y python-pip supervisor && \
- pip install /deps/swsssdk*.whl && \
- apt-get remove -y python-pip && \
- apt-get purge -y && apt-get autoclean -y && apt-get autoremove -y && \
- rm -rf /deps ~/.cache
-
-COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
-
-ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-lldp/supervisord.conf b/dockers/docker-lldp/supervisord.conf
deleted file mode 100644
index faff70ed06fa..000000000000
--- a/dockers/docker-lldp/supervisord.conf
+++ /dev/null
@@ -1,19 +0,0 @@
-[supervisord]
-nodaemon=true
-
-[program:lldpd]
-# https://github.com/vincentbernat/lldpd/commit/9856f2792c301116cc4a3fcfba91b9672ee5db1f
-# - `-d` means to stay in foreground, log to syslog
-# - `-dd` means to stay in foreground, log warnings to console
-# - `-ddd` means to stay in foreground, log warnings and info to console
-# - `-dddd` means to stay in foreground, log all to console
-command=/usr/sbin/lldpd -d -I Ethernet*,eth*
-priority=100
-
-[program:lldpsyncd]
-command=/usr/sbin/lldpsyncd
-priority=200
-
-[program:rsyslogd]
-command=/usr/sbin/rsyslogd -n
-priority=1
diff --git a/dockers/docker-mlnx-sswsyncd-rpc/Dockerfile b/dockers/docker-mlnx-sswsyncd-rpc/Dockerfile
deleted file mode 100644
index 4d1b3e49bcda..000000000000
--- a/dockers/docker-mlnx-sswsyncd-rpc/Dockerfile
+++ /dev/null
@@ -1,38 +0,0 @@
-FROM docker-base
-
-## Make apt-get non-interactive
-ENV DEBIAN_FRONTEND=noninteractive
-
-## Pre-install the fundamental packages
-RUN apt-get update \
- && apt-get -y install \
- net-tools
-
-COPY deps /deps
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \
- dpkg_apt /deps/python-tabulate_*.deb \
- && dpkg_apt /deps/applibs_*.deb \
- && dpkg_apt /deps/applibs-dev_*.deb \
- && dpkg_apt /deps/sx-complib_*.deb \
- && dpkg_apt /deps/sxd-libs_*.deb \
- && dpkg_apt /deps/sx-scew_*.deb \
- && dpkg_apt /deps/sx-examples_*.deb \
- && dpkg_apt /deps/sx-gen-utils_*.deb \
- && dpkg_apt /deps/python-sdk-api_*.deb \
- && dpkg_apt /deps/sx-libnl_*.deb \
- && dpkg_apt /deps/iproute2_*.deb \
- && dpkg_apt /deps/libsswsdk_*.deb \
- && dpkg_apt /deps/libthrift-0.9.3_*.deb \
- && dpkg_apt /deps/libthrift-dev_*.deb
-
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \
- dpkg_apt /deps/mlnx-sai_*.deb \
- && dpkg_apt /deps/sswsyncd-saithrift_*.deb
-
-## Clean up
-RUN apt-get clean -y ; apt-get autoclean -y ; apt-get autoremove -y ; rm -rf /deps
-
-ENTRYPOINT service rsyslog start \
- && mkdir -p /dev/sxdevs && ( [ -e /dev/sxdevs/sxcdev ] || mknod /dev/sxdevs/sxcdev c 231 193 ) \
- && service sswsyncd start \
- && /bin/bash
diff --git a/dockers/docker-mlnx-sswsyncd/Dockerfile b/dockers/docker-mlnx-sswsyncd/Dockerfile
deleted file mode 100755
index 631ff2e18030..000000000000
--- a/dockers/docker-mlnx-sswsyncd/Dockerfile
+++ /dev/null
@@ -1,33 +0,0 @@
-FROM docker-base
-
-## Make apt-get non-interactive
-ENV DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update
-
-## Pre-install the fundamental packages
-RUN apt-get update \
- && apt-get -y install \
- net-tools
-
-COPY deps /deps
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-tabulate_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/applibs_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/applibs-dev_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sx-complib_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sxd-libs_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sx-scew_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sx-examples_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sx-gen-utils_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-sdk-api_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sx-libnl_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/iproute2_*.deb
-
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/mlnx-sai_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libsswsdk_*.deb
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sswsyncd_*.deb
-
-ENTRYPOINT service rsyslog start \
- && mkdir -p /dev/sxdevs && ( [ -e /dev/sxdevs/sxcdev ] || mknod /dev/sxdevs/sxcdev c 231 193 ) \
- && sleep 5 && service sswsyncd start \
- && /bin/bash
diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2
index 587d8f4db2ee..9fba8d17b9d6 100755
--- a/dockers/docker-orchagent/Dockerfile.j2
+++ b/dockers/docker-orchagent/Dockerfile.j2
@@ -28,8 +28,8 @@ RUN rm -rf /debs
COPY ["arp_update", "start.sh", "orchagent.sh", "swssconfig.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
-COPY ["ipinip.json.j2", "/usr/share/sonic/templates/"]
-COPY ["mirror.json.j2", "/usr/share/sonic/templates/"]
-COPY ["ports.json.j2", "/usr/share/sonic/templates/"]
+
+## Copy all Jinja2 template files into the templates folder
+COPY ["*.j2", "/usr/share/sonic/templates/"]
ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-orchagent/mirror.json.j2 b/dockers/docker-orchagent/mirror.json.j2
deleted file mode 100644
index 3a3fc6eed079..000000000000
--- a/dockers/docker-orchagent/mirror.json.j2
+++ /dev/null
@@ -1,24 +0,0 @@
-[
-{% if MIRROR_SESSION %}
-{% for session in MIRROR_SESSION %}
- {
- "MIRROR_SESSION_TABLE:{{session}}": {
- "src_ip": "{{ MIRROR_SESSION[session]['src_ip'] }}",
- "dst_ip": "{{ MIRROR_SESSION[session]['dst_ip'] }}",
-{% if onie_switch_asic == "mlnx" %}
- "gre_type": "0x6558",
- "queue": "1",
-{% else %}
- "gre_type": "0x88be",
- "queue": "0",
-{% endif %}
- "dscp": "8",
- "ttl": "255"
- },
- "OP": "SET"
- }{% if not loop.last %},{% endif %}
-
-{% endfor %}
-{% endif %}
-]
-
diff --git a/dockers/docker-orchagent/msn27xx.32ports.buffers.json.j2 b/dockers/docker-orchagent/msn27xx.32ports.buffers.json.j2
new file mode 100644
index 000000000000..ce1ddedbba37
--- /dev/null
+++ b/dockers/docker-orchagent/msn27xx.32ports.buffers.json.j2
@@ -0,0 +1,287 @@
+[
+{% set port_names_list = [] %}
+{% for port in PORT %}
+ {%- if port_names_list.append(port) %}{% endif %}
+{% endfor %}
+{% set port_names = port_names_list | join(',') %}
+ {
+ "BUFFER_POOL_TABLE:ingress_lossy_pool": {
+ "size": "6422528",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_POOL_TABLE:egress_lossless_pool": {
+ "size": "7291456",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_POOL_TABLE:egress_lossy_pool": {
+ "size": "8254464",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL_TABLE:ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL_TABLE:ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:egress_lossless_profile": {
+ "pool":"[BUFFER_POOL_TABLE:egress_lossless_pool]",
+ "size":"1518",
+ "dynamic_th":"7"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:egress_lossy_profile": {
+ "pool":"[BUFFER_POOL_TABLE:egress_lossy_pool]",
+ "size":"4096",
+ "dynamic_th":"7"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:pg_lossy_profile": {
+ "pool":"[BUFFER_POOL_TABLE:ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:q_lossless_profile": {
+ "pool":"[BUFFER_POOL_TABLE:egress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PROFILE_TABLE:q_lossy_profile": {
+ "pool":"[BUFFER_POOL_TABLE:egress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"1"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PORT_INGRESS_PROFILE_LIST:{{ port_names }}": {
+ "profile_list" : "[BUFFER_PROFILE_TABLE:ingress_lossless_profile],[BUFFER_PROFILE_TABLE:ingress_lossy_profile]"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PORT_EGRESS_PROFILE_LIST:{{ port_names }}": {
+ "profile_list" : "[BUFFER_PROFILE_TABLE:egress_lossless_profile],[BUFFER_PROFILE_TABLE:egress_lossy_profile]"
+ },
+ "OP": "SET"
+ },
+
+{# The following template part is for variable PG profile configuration #}
+{% set non_pg_lossless_pool_size = 866726 %}
+{% set pg_range = '3-4' %}
+{# Lists of supported speed and cable length #}
+{% set supported_speed = [10000, 25000, 40000, 50000, 100000] %}
+{% set supported_cable = [5, 40, 300] %}
+
+{# The key in this lictionary consist of two parts: (port speed)_(cable length) #}
+{%- set portconfig2profile = {
+ '10000_5' : 'pg_lossless_10G_5m_profile',
+ '25000_5' : 'pg_lossless_25G_5m_profile',
+ '40000_5' : 'pg_lossless_40G_5m_profile',
+ '50000_5' : 'pg_lossless_50G_5m_profile',
+ '100000_5' : 'pg_lossless_100G_5m_profile',
+
+ '10000_40' : 'pg_lossless_10G_40m_profile',
+ '25000_40' : 'pg_lossless_25G_40m_profile',
+ '40000_40' : 'pg_lossless_40G_40m_profile',
+ '50000_40' : 'pg_lossless_50G_40m_profile',
+ '100000_40' : 'pg_lossless_100G_40m_profile',
+
+ '10000_300' : 'pg_lossless_10G_300m_profile',
+ '25000_300' : 'pg_lossless_25G_300m_profile',
+ '40000_300' : 'pg_lossless_40G_300m_profile',
+ '50000_300' : 'pg_lossless_50G_300m_profile',
+ '100000_300': 'pg_lossless_100G_300m_profile'
+ }
+-%}
+
+{# PG profiles. All profiles reffered in portconfig2profile dictionary should be declared here #}
+{# Only those which were actually used will be created in SAI #}
+{%- set pg_profiles = {
+ 'pg_lossless_10G_5m_profile': { 'xon': 18432, 'xoff': 16384, 'size': 34816, 'dynamic_th': 1 },
+ 'pg_lossless_25G_5m_profile': { 'xon': 18432, 'xoff': 16384, 'size': 34816, 'dynamic_th': 1 },
+ 'pg_lossless_40G_5m_profile': { 'xon': 18432, 'xoff': 16384, 'size': 34816, 'dynamic_th': 1 },
+ 'pg_lossless_50G_5m_profile': { 'xon': 18432, 'xoff': 16384, 'size': 34816, 'dynamic_th': 1 },
+ 'pg_lossless_100G_5m_profile': { 'xon': 18432, 'xoff': 18432, 'size': 36864, 'dynamic_th': 1 },
+
+ 'pg_lossless_10G_40m_profile': { 'xon': 18432, 'xoff': 18432, 'size': 36864, 'dynamic_th': 1 },
+ 'pg_lossless_25G_40m_profile': { 'xon': 18432, 'xoff': 21504, 'size': 39936, 'dynamic_th': 1 },
+ 'pg_lossless_40G_40m_profile': { 'xon': 18432, 'xoff': 23552, 'size': 41984, 'dynamic_th': 1 },
+ 'pg_lossless_50G_40m_profile': { 'xon': 18432, 'xoff': 23552, 'size': 41984, 'dynamic_th': 1 },
+ 'pg_lossless_100G_40m_profile': { 'xon': 18432, 'xoff': 35840, 'size': 54272, 'dynamic_th': 1 },
+
+ 'pg_lossless_10G_300m_profile': { 'xon': 18432, 'xoff': 30720, 'size': 49152, 'dynamic_th': 1 },
+ 'pg_lossless_25G_300m_profile': { 'xon': 18432, 'xoff': 53248, 'size': 71680, 'dynamic_th': 1 },
+ 'pg_lossless_40G_300m_profile': { 'xon': 18432, 'xoff': 75776, 'size': 94208, 'dynamic_th': 1 },
+ 'pg_lossless_50G_300m_profile': { 'xon': 18432, 'xoff': 75776, 'size': 94208, 'dynamic_th': 1 },
+ 'pg_lossless_100G_300m_profile':{ 'xon': 18432, 'xoff': 165888,'size': 184320,'dynamic_th': 1 },
+ }
+-%}
+
+{# Port configuration to cable length look-up table #}
+{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
+{# Roles described in the minigraph #}
+{% set ports2cable = {
+ 'ToRRouter_Server' : '5',
+ 'LeafRouter_ToRRouter' : '40',
+ 'SpineRouter_LeafRouter' : '300'
+ }
+%}
+
+{% set switch_role = DEVICE_METADATA['localhost']['type'] %}
+
+{%- macro cable_length(port_name) -%}
+ {%- set cable_len = [] -%}
+ {%- for local_port in DEVICE_NEIGHBOR -%}
+ {%- if local_port == port_name -%}
+ {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor_role = neighbor.type -%}
+ {%- set roles1 = switch_role + '_' + neighbor_role %}
+ {%- set roles2 = neighbor_role + '_' + switch_role -%}
+ {%- if roles1 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
+ {%- elif roles2 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
+ {%- endif -%}
+ {% endif %}
+ {% endif %}
+ {%- endfor -%}
+ {%- if cable_len -%}
+ {{ cable_len.0 }}
+ {%- else -%}
+ {{ supported_cable | last }}
+ {%- endif -%}
+{% endmacro %}
+
+{%- macro find_closest_greater_config(speed, cable) -%}
+{%- set new_speed = [] -%}
+{%- for std_speed in supported_speed -%}
+ {%- if std_speed | int >= speed | int -%}
+ {%- if new_speed.append(std_speed) -%}{%- endif -%}
+ {% endif -%}
+{%- endfor -%}
+{%- set new_cable = [] -%}
+{%- for std_cable in supported_cable -%}
+ {% if std_cable | int >= cable | int -%}
+ {%- if new_cable.append(std_cable) -%}{%- endif -%}
+ {% endif %}
+{%- endfor -%}
+{{ new_speed.0 }}_{{ new_cable.0 }}
+{%- endmacro -%}
+
+{% set ingress_lossless_pg_pool_size = [] %}
+{% set used_pg_profiles = [] %}
+{% for port in PORT %}
+ {%- if PORT[port].speed -%}
+ {%- set speed = PORT[port]['speed'] -%}
+ {% else %}
+ {%- set speed = supported_speed|last -%}
+ {%- endif -%}
+ {%- set cable = cable_length(port) -%}
+ {%- set port_config = speed|string + '_' + cable -%}
+ {%- if not port_config in portconfig2profile -%}
+ {% set port_config = find_closest_greater_config(speed, cable) -%}
+ {%- endif -%}
+ {% set profile = portconfig2profile[port_config] -%}
+ {% if ingress_lossless_pg_pool_size.append(pg_profiles[profile]['size']) %}{% endif %}
+ {# add to list profiles which were actually used #}
+ {%- if profile not in used_pg_profiles and used_pg_profiles.append(profile) %}{% endif -%}
+ {
+ "BUFFER_PG_TABLE:{{ port }}:{{ pg_range }}": {
+ "profile" : "[BUFFER_PROFILE_TABLE:{{ profile }}]"
+ },
+ "OP": "SET"
+ },
+{% endfor -%}
+
+{# PG profiles declaration #}
+
+{% for profile_name in used_pg_profiles %}
+ {%- set profile_config = pg_profiles[profile_name] %}
+ {
+ "BUFFER_PROFILE_TABLE:{{ profile_name }}": {
+ "pool":"[BUFFER_POOL_TABLE:ingress_lossless_pool]",
+ "xon":"{{ profile_config['xon'] }}",
+ "xoff":"{{ profile_config['xoff'] }}",
+ "size":"{{ profile_config['size'] }}",
+ "dynamic_th":"{{ profile_config['dynamic_th'] }}"
+ },
+ "OP": "SET"
+ },
+{% endfor -%}
+
+ {# Lossless pool declaration #}
+ {
+ "BUFFER_POOL_TABLE:ingress_lossless_pool": {
+ "size": "{{ ingress_lossless_pg_pool_size | sum + non_pg_lossless_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_PG_TABLE:{{ port_names }}:0-1": {
+ "profile" : "[BUFFER_PROFILE_TABLE:pg_lossy_profile]"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_QUEUE_TABLE:{{ port_names }}:3-4": {
+ "profile" : "[BUFFER_PROFILE_TABLE:q_lossless_profile]"
+ },
+ "OP": "SET"
+ },
+ {
+ "BUFFER_QUEUE_TABLE:{{ port_names }}:0-1": {
+ "profile" : "[BUFFER_PROFILE_TABLE:q_lossy_profile]"
+ },
+ "OP": "SET"
+ },
+ {
+ "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE:AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ },
+ "OP": "SET"
+ },
+ {
+ "PORT_QOS_MAP_TABLE:{{ port_names }}": {
+ "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE:AZURE]"
+ },
+ "OP": "SET"
+ }
+]
diff --git a/dockers/docker-orchagent/orchagent.sh b/dockers/docker-orchagent/orchagent.sh
index 7103afcb81e9..f92dfe5fd543 100755
--- a/dockers/docker-orchagent/orchagent.sh
+++ b/dockers/docker-orchagent/orchagent.sh
@@ -2,9 +2,7 @@
# Export platform information. Required to be able to write
# vendor specific code.
-export platform=`sonic-cfggen -v onie_switch_asic`
-
-ASIC=`sonic-cfggen -y /etc/sonic/sonic_version.yml -v asic_type`
+export platform=`sonic-cfggen -y /etc/sonic/sonic_version.yml -v asic_type`
MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'`
@@ -16,9 +14,9 @@ ORCHAGENT_ARGS="-d /var/log/swss "
ORCHAGENT_ARGS+="-b 8192 "
# Add platform specific arguments if necessary
-if [ "$ASIC" == "broadcom" ]; then
+if [ "$platform" == "broadcom" ]; then
ORCHAGENT_ARGS+="-m $MAC_ADDRESS"
-elif [ "$ASIC" == "cavium" ]; then
+elif [ "$platform" == "cavium" ]; then
ORCHAGENT_ARGS+="-m $MAC_ADDRESS"
fi
diff --git a/dockers/docker-orchagent/start.sh b/dockers/docker-orchagent/start.sh
index 0931321a9436..9f3ba3cb078d 100755
--- a/dockers/docker-orchagent/start.sh
+++ b/dockers/docker-orchagent/start.sh
@@ -2,8 +2,8 @@
mkdir -p /etc/swss/config.d/
+sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/switch.json.j2 > /etc/swss/config.d/switch.json
sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/ipinip.json.j2 > /etc/swss/config.d/ipinip.json
-sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/mirror.json.j2 > /etc/swss/config.d/mirror.json
sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/ports.json.j2 > /etc/swss/config.d/ports.json
export platform=`sonic-cfggen -v platform`
@@ -22,6 +22,10 @@ supervisorctl start neighsyncd
supervisorctl start swssconfig
+supervisorctl start vlanmgrd
+
+supervisorctl start intfmgrd
+
# Start arp_update when VLAN exists
VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'`
if [ "$VLAN" != "" ]; then
diff --git a/dockers/docker-orchagent/supervisord.conf b/dockers/docker-orchagent/supervisord.conf
index 09850b13d4a1..95e92be622bb 100644
--- a/dockers/docker-orchagent/supervisord.conf
+++ b/dockers/docker-orchagent/supervisord.conf
@@ -67,3 +67,19 @@ autostart=false
autorestart=true
stdout_logfile=syslog
stderr_logfile=syslog
+
+[program:vlanmgrd]
+command=/usr/bin/vlanmgrd
+priority=9
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:intfmgrd]
+command=/usr/bin/intfmgrd
+priority=10
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
diff --git a/dockers/docker-orchagent/switch.json.j2 b/dockers/docker-orchagent/switch.json.j2
new file mode 100644
index 000000000000..7a8c3522ecee
--- /dev/null
+++ b/dockers/docker-orchagent/switch.json.j2
@@ -0,0 +1,18 @@
+{# set default hash seed to 0 #}
+{% set hash_seed = 0 %}
+{% if DEVICE_METADATA.localhost.type %}
+{% if DEVICE_METADATA.localhost.type == "ToRRouter" %}
+{% set hash_seed = 10 %}
+{% elif DEVICE_METADATA.localhost.type == "LeafRouter" %}
+{% set hash_seed = 20 %}
+{% endif %}
+{% endif %}
+[
+ {
+ "SWITCH_TABLE:switch": {
+ "ecmp_hash_seed": "{{ hash_seed }}",
+ "lag_hash_seed": "{{ hash_seed }}"
+ },
+ "OP": "SET"
+ }
+]
diff --git a/dockers/docker-orchagent/swssconfig.sh b/dockers/docker-orchagent/swssconfig.sh
index 55a22c5353c8..3458ddae61e6 100755
--- a/dockers/docker-orchagent/swssconfig.sh
+++ b/dockers/docker-orchagent/swssconfig.sh
@@ -2,18 +2,6 @@
set -e
-function config_acl {
- if [ -f "/etc/sonic/acl.json" ]; then
- mkdir -p /etc/swss/config.d/acl
- rm -rf /etc/swss/config.d/acl/*
- translate_acl -m /etc/sonic/minigraph.xml -o /etc/swss/config.d/acl /etc/sonic/acl.json
- for filename in /etc/swss/config.d/acl/*.json; do
- [ -e "$filename" ] || break
- swssconfig $filename
- done
- fi
-}
-
function fast_reboot {
case "$(cat /proc/cmdline)" in
*fast-reboot*)
@@ -39,7 +27,7 @@ fast_reboot
HWSKU=`sonic-cfggen -m /etc/sonic/minigraph.xml -d -v "DEVICE_METADATA['localhost']['hwsku']"`
-SWSSCONFIG_ARGS="00-copp.config.json ipinip.json mirror.json ports.json "
+SWSSCONFIG_ARGS="00-copp.config.json ipinip.json ports.json switch.json "
if [ "$HWSKU" == "Force10-S6000" ]; then
SWSSCONFIG_ARGS+="td2.32ports.buffers.json td2.32ports.qos.json "
@@ -49,12 +37,10 @@ elif [ "$HWSKU" == "Arista-7050-QX32" ]; then
SWSSCONFIG_ARGS+="td2.32ports.buffers.json td2.32ports.qos.json "
elif [[ "$HWSKU" == "ACS-MSN27"* ]]; then
sonic-cfggen -m /etc/sonic/minigraph.xml -t /usr/share/sonic/templates/msn27xx.32ports.buffers.json.j2 > /etc/swss/config.d/msn27xx.32ports.buffers.json
- SWSSCONFIG_ARGS+="msn27xx.32ports.buffers.json msn2700.32ports.qos.json "
+ SWSSCONFIG_ARGS+="msn27xx.32ports.buffers.json msn27xx.32ports.qos.json "
fi
for file in $SWSSCONFIG_ARGS; do
swssconfig /etc/swss/config.d/$file
sleep 1
done
-
-config_acl
diff --git a/dockers/docker-platform-monitor/lm-sensors.sh b/dockers/docker-platform-monitor/lm-sensors.sh
index 61e90c09a8e3..2f4768a8cdda 100755
--- a/dockers/docker-platform-monitor/lm-sensors.sh
+++ b/dockers/docker-platform-monitor/lm-sensors.sh
@@ -3,7 +3,19 @@
# Based off /etc/init.d/lm-sensors
#
-/usr/bin/sensors -s > /dev/null 2>&1
+
+# NOTE: lm-sensors v3.3.5 appears to have a bug. If `sensors -s` is called, it
+# will first load /etc/sensors.conf, then load all files in /etc/sensors.d/,
+# overriding any values that may have already been specified in
+# /etc/sensors.conf. However, it appears this overriding is not taking place.
+# As a workaround, as long as a platform-specific sensors.conf has been copied
+# to /etc/sensors.d/, we will ONLY load that file, otherwise we load the default.
+if [ -e /etc/sensors.d/sensors.conf ]; then
+ /usr/bin/sensors -s -c /etc/sensors.d/sensors.conf > /dev/null 2>&1
+else
+ /usr/bin/sensors -s > /dev/null 2>&1
+fi
+
/usr/bin/sensors > /dev/null 2>&1
# Currently, there is no way to run sensord in the foreground, so we
diff --git a/dockers/docker-ptf/Dockerfile.j2 b/dockers/docker-ptf/Dockerfile.j2
index 1d1231d9418e..01312687b93c 100644
--- a/dockers/docker-ptf/Dockerfile.j2
+++ b/dockers/docker-ptf/Dockerfile.j2
@@ -40,6 +40,7 @@ RUN sed --in-place 's/httpredir.debian.org/debian-archive.trafficmanager.net/' /
iputils-ping \
hping3 \
curl \
+ tcpdump \
python \
python-dev \
python-scapy
diff --git a/dockers/docker-snmp/Dockerfile b/dockers/docker-snmp/Dockerfile
deleted file mode 100644
index 6a79db976adc..000000000000
--- a/dockers/docker-snmp/Dockerfile
+++ /dev/null
@@ -1,48 +0,0 @@
-FROM docker-base
-
-COPY deps/snmp_*.deb deps/snmpd_*.deb deps/libsnmp-base_*.deb deps/libsnmp30_*.deb /deps/
-COPY deps/python3/*.whl /python3/
-
-# enable -O for all Python calls
-ENV PYTHONOPTIMIZE 1
-
-## Make apt-get non-interactive
-ENV DEBIAN_FRONTEND=noninteractive
-
-## Pre-install the fundamental packages
-## Install SNMP subagent
-## Note: dpkg_apt function has the benefit to detect missing .deb file
-## Clean up
-RUN apt-get update && \
- dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } && \
- dpkg_apt /deps/libsnmp-base_*.deb && \
- dpkg_apt /deps/libsnmp30_*.deb && \
- dpkg_apt /deps/snmp_*.deb && \
- dpkg_apt /deps/snmpd_*.deb && \
- rm -rf /deps
-
-# install subagent
-RUN apt-get -y install build-essential wget libssl-dev openssl supervisor && \
- rm -rf /var/lib/apt/lists/* && \
- wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz && \
- tar xvf Python-3.5.2.tgz && cd Python-3.5.2 && \
- ./configure --without-doc-strings --prefix=/usr --without-pymalloc --enable-shared && \
- make && make install && \
- ldconfig && \
- cd .. && rm -rf Python-3.5.2 && rm Python-3.5.2.tgz && \
- pip3 install --no-cache-dir /python3/*py3*.whl hiredis && \
- rm -rf /python3 && \
- python3 -m acs_ax_impl install && \
- python3 -m pip uninstall -y pip setuptools && \
- /bin/bash -c "rm -rf /usr/lib/python3.5/{unittest,lib2to3,tkinter,idlelib,email,test}" && \
- apt-get -y purge build-essential wget libssl-dev openssl && \
- apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && \
- find / | grep -E "__pycache__" | xargs rm -rf && \
- rm -rf ~/.cache
-
-COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
-
-## Although exposing ports is not need for host net mode, keep it for possible bridge mode
-EXPOSE 161/udp 162/udp
-
-ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-snmp/supervisord.conf b/dockers/docker-snmp/supervisord.conf
deleted file mode 100644
index c954add628d0..000000000000
--- a/dockers/docker-snmp/supervisord.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-[supervisord]
-nodaemon=true
-
-[program:snmpd]
-command=/usr/sbin/snmpd -f -LS4d -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf,ifTable,ifXTable -p /run/snmpd.pid
-priority=100
-
-[program:acs-snmp-subagent]
-command=/usr/bin/env python3 -m acs_ax_impl
-priority=200
-
-[program:rsyslogd]
-command=/usr/sbin/rsyslogd -n
-priority=1
diff --git a/dockers/docker-sswsyncd/Dockerfile b/dockers/docker-sswsyncd/Dockerfile
deleted file mode 100755
index 0f555d8b51bf..000000000000
--- a/dockers/docker-sswsyncd/Dockerfile
+++ /dev/null
@@ -1,27 +0,0 @@
-FROM docker-base
-
-COPY \
- deps/python-tabulate_*.deb \
- deps/libopennsl_*.deb \
- deps/libsaibcm_*.deb \
- deps/libsswsdk_*.deb \
- deps/sswsyncd_*.deb \
- /deps/
-
-## Make apt-get non-interactive
-ENV DEBIAN_FRONTEND=noninteractive
-
-## Install packages
-## Clean up
-RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } && \
- dpkg_apt /deps/python-tabulate_*.deb && \
- dpkg_apt /deps/libopennsl_*.deb && \
- dpkg_apt /deps/libsaibcm_*.deb && \
- dpkg_apt /deps/libsswsdk_*.deb && \
- dpkg_apt /deps/sswsyncd_*.deb && \
- apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && \
- rm -rf /deps
-
-ENTRYPOINT service rsyslog start \
- && service sswsyncd start \
- && /bin/bash
diff --git a/dockers/docker-teamd/start.sh b/dockers/docker-teamd/start.sh
index 6b0a3d785894..6e80f6eb9a83 100755
--- a/dockers/docker-teamd/start.sh
+++ b/dockers/docker-teamd/start.sh
@@ -17,6 +17,12 @@ fi
for pc in `sonic-cfggen -d -v "PORTCHANNEL.keys() | join(' ') if PORTCHANNEL"`; do
sonic-cfggen -d -a '{"pc":"'$pc'","hwaddr":"'$MAC_ADDRESS'"}' -t /usr/share/sonic/templates/teamd.j2 > $TEAMD_CONF_PATH/$pc.conf
+ # bring down all member ports before starting teamd
+ for member in $(sonic-cfggen -d -v "PORTCHANNEL['$pc']['members'] | join(' ')" ); do
+ if [ -L /sys/class/net/$member ]; then
+ ip link set $member down
+ fi
+ done
done
mkdir -p /var/sonic
diff --git a/files/Aboot/boot0.j2 b/files/Aboot/boot0.j2
index b88c0ec35b39..8ea085bf5e8d 100644
--- a/files/Aboot/boot0.j2
+++ b/files/Aboot/boot0.j2
@@ -65,9 +65,6 @@ extract_image() {
## vfat does not support symbol link
if [ -n "$sonic_upgrade" ] || [ "$rootfs_type" != "vfat" ]; then
- ## on ext4, other doesn't have access to the flash by default
- chmod o+rx "$target_path"
-
mkdir -p "$image_path/{{ DOCKERFS_DIR }}"
if [ -n "$sonic_upgrade" ]; then
diff --git a/files/build_templates/snmp.service.j2 b/files/build_templates/snmp.service.j2
index 493d6bd8fcfd..08c41a52a5f7 100644
--- a/files/build_templates/snmp.service.j2
+++ b/files/build_templates/snmp.service.j2
@@ -1,7 +1,7 @@
[Unit]
Description=SNMP container
-Requires=database.service
-After=database.service
+Requires=database.service swss.service
+After=database.service swss.service
[Service]
User={{ sonicadmin_user }}
diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2
index 04f5181ff610..37fcfbc56fcb 100644
--- a/files/build_templates/sonic_debian_extension.j2
+++ b/files/build_templates/sonic_debian_extension.j2
@@ -188,12 +188,20 @@ sudo dpkg --root=$FILESYSTEM_ROOT -P {{ debname }}
sudo rm -f $FILESYSTEM_ROOT/usr/sbin/policy-rc.d
+## Revise /etc/init.d/networking for Arista switches
+if [ "$image_type" = "aboot" ]; then
+ sudo sed -i 's/udevadm settle/udevadm settle -E \/sys\/class\/net\/eth0/' $FILESYSTEM_ROOT/etc/init.d/networking
+fi
+
## copy platform rc.local
sudo cp $IMAGE_CONFIGS/platform/rc.local $FILESYSTEM_ROOT/etc/
{% if installer_images.strip() -%}
{% for image in installer_images.strip().split(' ') -%}
+{% set imagefilename = image.split('/')|last -%}
+{% set imagename = imagefilename.split('.')|first -%}
sudo LANG=C chroot $FILESYSTEM_ROOT docker load < {{image}}
+sudo LANG=C chroot $FILESYSTEM_ROOT docker tag {{imagename}}:latest {{imagename}}:$(sonic_get_version)
{% endfor %}
sudo chroot $FILESYSTEM_ROOT service docker stop
{% for script in installer_start_scripts.split(' ') -%}
diff --git a/files/build_templates/swss.service.j2 b/files/build_templates/swss.service.j2
index af922530d8a2..74fafb003767 100644
--- a/files/build_templates/swss.service.j2
+++ b/files/build_templates/swss.service.j2
@@ -17,6 +17,7 @@ ExecStartPre=/bin/bash -c "while true; do if [ \"$(/usr/bin/docker exec database
ExecStartPre=/usr/bin/docker exec database redis-cli -n 0 FLUSHDB
ExecStartPre=/usr/bin/docker exec database redis-cli -n 1 FLUSHDB
ExecStartPre=/usr/bin/docker exec database redis-cli -n 2 FLUSHDB
+ExecStartPre=/usr/bin/docker exec database redis-cli -n 5 FLUSHDB
{% if sonic_asic_platform == 'mellanox' %}
TimeoutStartSec=3min
diff --git a/files/dhcp/graphserviceurl b/files/dhcp/graphserviceurl
index f255cdff9877..5c5d801cbc8c 100644
--- a/files/dhcp/graphserviceurl
+++ b/files/dhcp/graphserviceurl
@@ -3,7 +3,7 @@ case $reason in
if [ -n "$new_minigraph_url" ]; then
echo $new_minigraph_url > /tmp/dhcp_graph_url
else
- echo "N/A" > /tmp/dhcp_graph_url
+ echo "default" > /tmp/dhcp_graph_url
fi
if [ -n "$new_acl_url" ]; then
echo $new_acl_url > /tmp/dhcp_acl_url
diff --git a/files/image_config/interfaces/interfaces-config.sh b/files/image_config/interfaces/interfaces-config.sh
index 400b89a594c7..28396774bfa1 100755
--- a/files/image_config/interfaces/interfaces-config.sh
+++ b/files/image_config/interfaces/interfaces-config.sh
@@ -1,6 +1,22 @@
#!/bin/bash
-sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 >/etc/network/interfaces
+SONIC_ASIC_TYPE=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v asic_type)
+SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}')
+
+# Align last byte of MAC if necessary
+if [ "$SONIC_ASIC_TYPE" == "mellanox" -o "$SONIC_ASIC_TYPE" == "centec" ]; then
+ last_byte=$(python -c "print '$SYSTEM_MAC_ADDRESS'[-2:]")
+ aligned_last_byte=$(python -c "print format(int(int('$last_byte', 16) & 0b11000000), '02x')") # put mask and take away the 0x prefix
+ SYSTEM_MAC_ADDRESS=$(python -c "print '$SYSTEM_MAC_ADDRESS'[:-2] + '$aligned_last_byte'") # put aligned byte into the end of MAC
+fi
+
+sonic-cfggen -d -a '{"hwaddr":"'$SYSTEM_MAC_ADDRESS'"}' -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces
+
+# Also store the system mac to configDB switch table. User configured switch_mac is not supported for now.
+/usr/bin/docker exec database redis-cli -n 4 hset SWITCH\|SWITCH_ATTR switch_mac $SYSTEM_MAC_ADDRESS
+
[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid
-service networking restart
+
+systemctl restart networking
+
ifdown lo && ifup lo
diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2
index 6521eb7a67e1..a06ff91518a7 100644
--- a/files/image_config/interfaces/interfaces.j2
+++ b/files/image_config/interfaces/interfaces.j2
@@ -55,19 +55,6 @@ iface {{ name }} {{ 'inet' if prefix | ipv4 else 'inet6' }} static
netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }}
#
{% endfor %}
-{% if VLAN %}
-# "|| true" is added to suppress the error when interface is already a member of VLAN
-{% for vlan in VLAN.keys()|sort %}
-{% for member in VLAN[vlan]['members'] %}
-allow-hotplug {{ member }}
-iface {{ member }} inet manual
- pre-up ifconfig {{ member }} up mtu 9100
- post-up brctl addif {{ vlan }} {{ member }} || true
- post-down ifconfig {{ member }} down
-#
-{% endfor %}
-{% endfor %}
-{% endif %}
{% if PORTCHANNEL %}
# "|| true" is added to suppress the error when interface is already a member of LAG
# "ip link show | grep -q master" is added to ensure interface is enslaved
@@ -83,19 +70,6 @@ iface {{ member }} inet manual
{% endfor %}
{% endif %}
{% endblock front_panel_interfaces %}
-{% block vlan_interfaces %}
-{% if VLAN_INTERFACE %}
-# Vlan interfaces
-{% for (name, prefix) in VLAN_INTERFACE.keys() | sort %}
-auto {{ name }}
-iface {{ name }} {{ 'inet' if prefix | ipv4 else 'inet6' }} static
- bridge_ports none
- address {{ prefix | ip }}
- netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }}
-{% endfor %}
-#
-{% endif %}
-{% endblock vlan_interfaces %}
{% block pc_interfaces %}
{% if PORTCHANNEL_INTERFACE %}
# Portchannel interfaces
diff --git a/files/image_config/ntp/ntp.conf.j2 b/files/image_config/ntp/ntp.conf.j2
index ae72820339be..d7df6bcd2e04 100644
--- a/files/image_config/ntp/ntp.conf.j2
+++ b/files/image_config/ntp/ntp.conf.j2
@@ -29,9 +29,13 @@ server {{ ntp_server }} iburst
#only listen on localhost and eth0 ips (default is to listen on all ip addresses)
interface ignore wildcard
+{% if MGMT_INTERFACE %}
{% for (mgmt_intf, mgmt_prefix) in MGMT_INTERFACE %}
interface listen {{ mgmt_prefix | ip }}
{% endfor %}
+{% else %}
+interface listen eth0
+{% endif %}
interface listen 127.0.0.1
# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
diff --git a/files/image_config/updategraph/updategraph b/files/image_config/updategraph/updategraph
index 4e9846fba024..b72bc6e2c1c8 100755
--- a/files/image_config/updategraph/updategraph
+++ b/files/image_config/updategraph/updategraph
@@ -20,8 +20,25 @@ if [ "$src" = "dhcp" ]; then
sleep 1
done
+ if [ "`cat /tmp/dhcp_graph_url`" = "default" ]; then
+ echo "No graph_url option in DHCP response. Skipping graph update and using existing minigraph."
+ if [ "$dhcp_as_static" = "true" ]; then
+ sed -i "/enabled=/d" /etc/sonic/updategraph.conf
+ echo "enabled=false" >> /etc/sonic/updategraph.conf
+ fi
+ exit 0
+ fi
if [ "`cat /tmp/dhcp_graph_url`" = "N/A" ]; then
- echo "No graph_url option in DHCP response. Skipping graph update."
+ echo "'N/A' found in DHCP response. Skipping graph update and generating an empty configuration."
+ echo '{"DEVICE_METADATA":' > /tmp/device_meta.json
+ sonic-cfggen -m /etc/sonic/minigraph.xml --var-json DEVICE_METADATA >> /tmp/device_meta.json
+ echo '}' >> /tmp/device_meta.json
+ if [ -f /etc/sonic/init_cfg.json ]; then
+ sonic-cfggen -j /tmp/device_meta.json -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json
+ else
+ cp -f /tmp/device_meta.json /etc/sonic/config_db.json
+ fi
+
if [ "$dhcp_as_static" = "true" ]; then
sed -i "/enabled=/d" /etc/sonic/updategraph.conf
echo "enabled=false" >> /etc/sonic/updategraph.conf
@@ -29,6 +46,7 @@ if [ "$src" = "dhcp" ]; then
exit 0
fi
+
HOSTNAME=`hostname -s`
GRAPH_URL=`sonic-cfggen -t /tmp/dhcp_graph_url -a "{\"hostname\": \"$HOSTNAME\"}"`
URL_REGEX='^(https?|ftp|file)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]$'
diff --git a/files/initramfs-tools/arista-convertfs.j2 b/files/initramfs-tools/arista-convertfs.j2
index 75ce011e839a..cea25bd39837 100644
--- a/files/initramfs-tools/arista-convertfs.j2
+++ b/files/initramfs-tools/arista-convertfs.j2
@@ -82,6 +82,13 @@ run_cmd() {
fi
}
+fixup_flash_permissions() {
+ # properly set flash permissions for others
+ # this allows the sonic admin user to have read access on the flash
+ local flash_mnt="$1"
+ chmod o+rx "$flash_mnt"
+}
+
# Extract kernel parameters
set -- $(cat /proc/cmdline)
for x in "$@"; do
@@ -111,7 +118,14 @@ if ! wait_for_root_dev; then
fi
# exit when the root is ext4
-blkid | grep "$root_dev.*vfat" -q || exit 0
+if ! blkid | grep "$root_dev.*vfat" -q; then
+ mkdir -p "$root_mnt"
+ mount -t ext4 "$root_dev" "$root_mnt"
+ fixup_flash_permissions "$root_mnt"
+ umount "$root_mnt"
+ rmdir "$root_mnt"
+ exit 0
+fi
# Get flash dev name
if [ -z "$block_flash" ]; then
@@ -176,3 +190,5 @@ run_cmd "$cmd" "$err_msg"
err_msg="Error: copying files form $tmp_mnt to $root_mnt failed"
cmd="cp -a $tmp_mnt/. $root_mnt/"
run_cmd "$cmd" "$err_msg"
+
+fixup_flash_permissions "$root_mnt"
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 2340177fd18b..60305c292b6b 100644
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -13,6 +13,7 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(INGRASYS_S8810_32Q_PLATFORM_MODULE) \
$(ACCTON_AS7712_32X_PLATFORM_MODULE) \
$(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
+ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
$(CEL_DX010_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES)
SONIC_INSTALLERS += $(SONIC_ONE_IMAGE)
diff --git a/platform/broadcom/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk
index 0d00fe1f7368..f4a2e65e5147 100755
--- a/platform/broadcom/platform-modules-inventec.mk
+++ b/platform/broadcom/platform-modules-inventec.mk
@@ -1,12 +1,17 @@
-# Inventec d7032q28b Platform modules
+# Inventec d7032q28b and d7054q28b Platform modules
-INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.0.0
+INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.1.0
+INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION = 1.1.0
export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION
+export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION
INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-inventec
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7032q28b-r0
SONIC_DPKG_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE)
-$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE)))
+
+INVENTEC_D7054Q28B_PLATFORM_MODULE = platform-modules-d7054q28b_$(INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
+$(INVENTEC_D7054Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7054q28b-r0
+$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7054Q28B_PLATFORM_MODULE)))
diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk
index ea804a69c0eb..5b66026f297f 100644
--- a/platform/broadcom/sai.mk
+++ b/platform/broadcom/sai.mk
@@ -1,9 +1,9 @@
-BRCM_SAI = libsaibcm_3.0.3.2-5_amd64.deb
-$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/libsaibcm_3.0.3.2-5_amd64.deb?sv=2015-04-05&sr=b&sig=MQE6FrxHs%2BIUPjRaSpWagcSjY6bbHLCUYasusxILkEs%3D&se=2031-06-07T21%3A50%3A36Z&sp=r"
+BRCM_SAI = libsaibcm_3.0.3.2-10_amd64.deb
+$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/libsaibcm_3.0.3.2-10_amd64.deb?sv=2015-04-05&sr=b&sig=tByZ7QDBsYlJ4UHbapnzqHYrbA8rD92%2FQXEpupITTmM%3D&se=2031-07-06T19%3A19%3A32Z&sp=r"
-BRCM_SAI_DEV = libsaibcm-dev_3.0.3.2-5_amd64.deb
+BRCM_SAI_DEV = libsaibcm-dev_3.0.3.2-10_amd64.deb
$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV)))
-$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/libsaibcm-dev_3.0.3.2-5_amd64.deb?sv=2015-04-05&sr=b&sig=o8bjWlxxYAM%2F95aSshRFJE57JwKVjRaH4jDU2lDEoMg%3D&se=2031-06-07T21%3A50%3A19Z&sp=r"
+$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/libsaibcm-dev_3.0.3.2-10_amd64.deb?sv=2015-04-05&sr=b&sig=T6U8sF%2BW8B%2FffBzPoUJ9peLcg2O9MunHBBKSu7SZOKo%3D&se=2031-07-06T19%3A19%3A52Z&sp=r"
SONIC_ONLINE_DEBS += $(BRCM_SAI) $(BRCM_SAI_DEV)
$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)
diff --git a/platform/broadcom/sdk.mk b/platform/broadcom/sdk.mk
index 04d540c64582..aff0cf07fe5c 100644
--- a/platform/broadcom/sdk.mk
+++ b/platform/broadcom/sdk.mk
@@ -1,4 +1,4 @@
-BRCM_OPENNSL_KERNEL = opennsl-modules-3.16.0-4-amd64_3.2.3.3-1_amd64.deb
-$(BRCM_OPENNSL_KERNEL)_URL = "https://sonicstorage.blob.core.windows.net/packages/opennsl-modules-3.16.0-4-amd64_3.2.3.3-1_amd64.deb?sv=2015-04-05&sr=b&sig=Uepf4z2wOadX%2F6OR%2BCoQzjv2tkwEZ2AspBiuo5sb25s%3D&se=2031-05-30T19%3A37%3A19Z&sp=r"
+BRCM_OPENNSL_KERNEL = opennsl-modules-3.16.0-4-amd64_3.2.3.3-2_amd64.deb
+$(BRCM_OPENNSL_KERNEL)_URL = "https://sonicstorage.blob.core.windows.net/packages/opennsl-modules-3.16.0-4-amd64_3.2.3.3-2_amd64.deb?sv=2015-04-05&sr=b&sig=RADtBDA9oZmwHnTzBY76ewajyJ8Af%2BchVCzNbe%2BPsbc%3D&se=2031-07-06T19%3A18%3A56Z&sp=r"
SONIC_ONLINE_DEBS += $(BRCM_OPENNSL_KERNEL)
diff --git a/platform/broadcom/sonic-platform-modules-arista b/platform/broadcom/sonic-platform-modules-arista
index d1417bff1778..f985b188326e 160000
--- a/platform/broadcom/sonic-platform-modules-arista
+++ b/platform/broadcom/sonic-platform-modules-arista
@@ -1 +1 @@
-Subproject commit d1417bff17780255d4cc371b315f620087673eb8
+Subproject commit f985b188326e480124ec49541b4fecc51a213889
diff --git a/platform/broadcom/sonic-platform-modules-dell b/platform/broadcom/sonic-platform-modules-dell
index 1abd4e6c41f6..f0e808fe518f 160000
--- a/platform/broadcom/sonic-platform-modules-dell
+++ b/platform/broadcom/sonic-platform-modules-dell
@@ -1 +1 @@
-Subproject commit 1abd4e6c41f633272667a5833a63ab6f8da15199
+Subproject commit f0e808fe518f336e4cb97fdaf25e35a752c24d89
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/conf/d7032q28b-modules.conf b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/conf/d7032q28b-modules.conf
deleted file mode 100644
index 29d4d50a4f9a..000000000000
--- a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/conf/d7032q28b-modules.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# /etc/modules: kernel modules to load at boot time.
-#
-# This file contains the names of kernel modules that should be loaded
-# at boot time, one per line. Lines beginning with "#" are ignored.
-
-lpc_ich
-i2c-i801
-i2c-mux
-i2c-mux-pca954x
-i2c-dev
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile
index cdabd612a66d..c43c47745229 100755
--- a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile
@@ -1,3 +1,7 @@
obj-m += inv_cpld.o inv_psoc.o
obj-m += inv_platform.o
+obj-m += inv_eeprom.o
+obj-m += swps.o
+swps-objs := inv_swps.o io_expander.o transceiver.o
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c
new file mode 100644
index 000000000000..b2dde612b610
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE 256
+
+#define SLICE_BITS (6)
+#define SLICE_SIZE (1 << SLICE_BITS)
+#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE)
+
+/* Each client has this additional data */
+struct eeprom_data {
+ struct mutex update_lock;
+ u8 valid; /* bitfield, bit!=0 if slice is valid */
+ unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */
+ u8 data[EEPROM_SIZE]; /* Register values */
+};
+
+
+static void inv_eeprom_update_client(struct i2c_client *client, u8 slice)
+{
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ int i, j;
+ int ret;
+ int addr;
+
+
+ mutex_lock(&data->update_lock);
+
+ if (!(data->valid & (1 << slice)) ||
+ time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
+ dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
+
+ addr = slice << SLICE_BITS;
+
+ ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF);
+ /* select the eeprom address */
+ if (ret < 0) {
+ dev_err(&client->dev, "address set failed\n");
+ goto exit;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
+ goto exit;
+ }
+
+ for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
+ for (j = i; j < (i+SLICE_SIZE); j++) {
+ int res;
+
+ res = i2c_smbus_read_byte(client);
+ if (res < 0) {
+ goto exit;
+ }
+
+ data->data[j] = res & 0xFF;
+ }
+ }
+
+ data->last_updated[slice] = jiffies;
+ data->valid |= (1 << slice);
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+}
+
+static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ u8 slice;
+
+
+ if (off > EEPROM_SIZE) {
+ return 0;
+ }
+ if (off + count > EEPROM_SIZE) {
+ count = EEPROM_SIZE - off;
+ }
+ if (count == 0) {
+ return 0;
+ }
+
+ /* Only refresh slices which contain requested bytes */
+ for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
+ inv_eeprom_update_client(client, slice);
+ }
+
+ memcpy(buf, &data->data[off], count);
+
+ return count;
+}
+
+static struct bin_attribute inv_eeprom_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = inv_eeprom_read,
+};
+
+static int inv_eeprom_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct eeprom_data *data;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memset(data->data, 0xff, EEPROM_SIZE);
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* create the sysfs eeprom file */
+ err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ if (err) {
+ goto exit_kfree;
+ }
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int inv_eeprom_remove(struct i2c_client *client)
+{
+ sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static const struct i2c_device_id inv_eeprom_id[] = {
+ { "inv_eeprom", 0 },
+ { }
+};
+
+static struct i2c_driver inv_eeprom_driver = {
+ .driver = {
+ .name = "inv_eeprom",
+ },
+ .probe = inv_eeprom_probe,
+ .remove = inv_eeprom_remove,
+ .id_table = inv_eeprom_id,
+};
+
+module_i2c_driver(inv_eeprom_driver);
+
+MODULE_AUTHOR("Inventec");
+MODULE_DESCRIPTION("Inventec D7032 Mother Board EEPROM driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c
index 71dda75b252f..52f6a5691d3e 100644
--- a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c
@@ -1,197 +1,198 @@
-#include
-//#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-//#include
-#define IO_EXPAND_BASE 64
-#define IO_EXPAND_NGPIO 16
-
-struct inv_i2c_board_info {
- int ch;
- int size;
- struct i2c_board_info *board_info;
-};
-
-#define bus_id(id) (id)
-static struct pca954x_platform_mode mux_modes_0[] = {
- {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
- {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
-};
-static struct pca954x_platform_mode mux_modes_0_0[] = {
- {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
- {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
- {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
- {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
-};
-
-static struct pca954x_platform_mode mux_modes_0_1[] = {
- {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
- {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
- {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
- {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
-};
-
-static struct pca954x_platform_mode mux_modes_0_2[] = {
- {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
- {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
- {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
- {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
-};
-
-static struct pca954x_platform_mode mux_modes_0_3[] = {
- {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
- {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
- {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
- {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
-};
-
-static struct pca954x_platform_data mux_data_0 = {
- .modes = mux_modes_0,
- .num_modes = 4,
-};
-static struct pca954x_platform_data mux_data_0_0 = {
- .modes = mux_modes_0_0,
- .num_modes = 8,
-};
-static struct pca954x_platform_data mux_data_0_1 = {
- .modes = mux_modes_0_1,
- .num_modes = 8,
-};
-static struct pca954x_platform_data mux_data_0_2 = {
- .modes = mux_modes_0_2,
- .num_modes = 8,
-};
-static struct pca954x_platform_data mux_data_0_3 = {
- .modes = mux_modes_0_3,
- .num_modes = 8,
-};
-
-static struct i2c_board_info i2c_device_info0[] __initdata = {
- {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
- {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
- {"pca9545", 0, 0x70, &mux_data_0, 0, 0},
-};
-
-static struct i2c_board_info i2c_device_info1[] __initdata = {
- {"pca9545", 0, 0x70, &mux_data_0, 0, 0},
-};
-
-static struct i2c_board_info i2c_device_info2[] __initdata = {
- {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
-};
-
-static struct i2c_board_info i2c_device_info3[] __initdata = {
- {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
-};
-
-static struct i2c_board_info i2c_device_info4[] __initdata = {
- {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
-};
-
-static struct i2c_board_info i2c_device_info5[] __initdata = {
- {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
-};
-
-
-static struct inv_i2c_board_info i2cdev_list[] = {
- {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0
- {1, ARRAY_SIZE(i2c_device_info1), i2c_device_info1 }, //smbus 1 or gpio11+12
-
- {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
- {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
- {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
- {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
- .scl_pin = 8,
- .sda_pin = 9,
-
- .udelay = 5, //5:100kHz
- .sda_is_open_drain = 0,
- .scl_is_open_drain = 0,
- .scl_is_output_only = 0
-};
-
-static struct i2c_gpio_platform_data i2c_gpio_platdata1 = {
- .scl_pin = 12,
- .sda_pin = 11,
-
- .udelay = 5, //5:100kHz
- .sda_is_open_drain = 0,
- .scl_is_open_drain = 0,
- .scl_is_output_only = 0
-};
-
-static struct platform_device device_i2c_gpio0 = {
- .name = "i2c-gpio",
- .id = 0, // adapter number
- .dev.platform_data = &i2c_gpio_platdata0,
-};
-
-static struct platform_device device_i2c_gpio1 = {
- .name = "i2c-gpio",
- .id = 1, // adapter number
- .dev.platform_data = &i2c_gpio_platdata1,
-};
-
-static int __init plat_redwood_x86_init(void)
-{
- struct i2c_adapter *adap = NULL;
- struct i2c_client *e = NULL;
- int ret = 0;
- int i,j;
-
- printk("el6661 plat_redwood_x86_init \n");
-
-#if 0 //disable for ICOS
- //use i2c-gpio
- //register i2c gpio
- //config gpio8,9 to gpio function
- outl( inl(0x500) | (1<<8 | 1<<9), 0x500);
-
- ret = platform_device_register(&device_i2c_gpio0);
- if (ret) {
- printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret);
- }
-
- outl( inl(0x500) | (1<<11 | 1<<12), 0x500);
- ret = platform_device_register(&device_i2c_gpio1);
- if (ret) {
- printk(KERN_ERR "i2c-gpio: device_i2c_gpio1 register fail %d\n", ret);
- }
-#endif
-
- for(i=0; i
+//#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+//#include
+#define IO_EXPAND_BASE 64
+#define IO_EXPAND_NGPIO 16
+
+struct inv_i2c_board_info {
+ int ch;
+ int size;
+ struct i2c_board_info *board_info;
+};
+
+#define bus_id(id) (id)
+static struct pca954x_platform_mode mux_modes_0[] = {
+ {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
+ {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
+};
+static struct pca954x_platform_mode mux_modes_0_0[] = {
+ {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
+ {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
+ {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
+ {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_1[] = {
+ {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
+ {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
+ {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
+ {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_2[] = {
+ {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
+ {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
+ {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
+ {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_3[] = {
+ {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
+ {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
+ {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
+ {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
+};
+
+static struct pca954x_platform_data mux_data_0 = {
+ .modes = mux_modes_0,
+ .num_modes = 4,
+};
+static struct pca954x_platform_data mux_data_0_0 = {
+ .modes = mux_modes_0_0,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_1 = {
+ .modes = mux_modes_0_1,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_2 = {
+ .modes = mux_modes_0_2,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_3 = {
+ .modes = mux_modes_0_3,
+ .num_modes = 8,
+};
+
+static struct i2c_board_info i2c_device_info0[] __initdata = {
+ {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
+ {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
+ {"pca9545", 0, 0x70, &mux_data_0, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info1[] __initdata = {
+ {"pca9545", 0, 0x70, &mux_data_0, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info2[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info3[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info4[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info5[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
+};
+
+
+static struct inv_i2c_board_info i2cdev_list[] = {
+ {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0
+ {1, ARRAY_SIZE(i2c_device_info1), i2c_device_info1 }, //smbus 1 or gpio11+12
+
+ {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
+ {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
+ {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
+ {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
+ .scl_pin = 8,
+ .sda_pin = 9,
+
+ .udelay = 5, //5:100kHz
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0
+};
+
+static struct i2c_gpio_platform_data i2c_gpio_platdata1 = {
+ .scl_pin = 12,
+ .sda_pin = 11,
+
+ .udelay = 5, //5:100kHz
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0
+};
+
+static struct platform_device device_i2c_gpio0 = {
+ .name = "i2c-gpio",
+ .id = 0, // adapter number
+ .dev.platform_data = &i2c_gpio_platdata0,
+};
+
+static struct platform_device device_i2c_gpio1 = {
+ .name = "i2c-gpio",
+ .id = 1, // adapter number
+ .dev.platform_data = &i2c_gpio_platdata1,
+};
+
+static int __init plat_redwood_x86_init(void)
+{
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *e = NULL;
+ int ret = 0;
+ int i,j;
+
+ printk("el6661 plat_redwood_x86_init \n");
+
+#if 0 //disable for ICOS
+ //use i2c-gpio
+ //register i2c gpio
+ //config gpio8,9 to gpio function
+ outl( inl(0x500) | (1<<8 | 1<<9), 0x500);
+
+ ret = platform_device_register(&device_i2c_gpio0);
+ if (ret) {
+ printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret);
+ }
+
+ outl( inl(0x500) | (1<<11 | 1<<12), 0x500);
+ ret = platform_device_register(&device_i2c_gpio1);
+ if (ret) {
+ printk(KERN_ERR "i2c-gpio: device_i2c_gpio1 register fail %d\n", ret);
+ }
+#endif
+
+ for(i=0; i
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "inv_swps.h"
+
+static int port_major;
+static int ioexp_total;
+static int port_total;
+static struct class *swp_class_p = NULL;
+static struct inv_platform_s *platform_p = NULL;
+static struct inv_ioexp_layout_s *ioexp_layout = NULL;
+static struct inv_port_layout_s *port_layout = NULL;
+
+static int
+__swp_match(struct device *dev,
+#ifdef SWPS_KERN_VER_AF_3_10
+
+ const void *data){
+#else
+ void *data){
+#endif
+
+ char *name = (char *)data;
+ if (strcmp(dev_name(dev), name) == 0)
+ return 1;
+ return 0;
+}
+
+
+struct device *
+get_swpdev_by_name(char *name){
+ struct device *dev = class_find_device(swp_class_p,
+ NULL,
+ name,
+ (const void *)__swp_match);
+ return dev;
+}
+
+
+static int
+sscanf_2_int(const char *buf) {
+
+ int result = -EBFONT;
+ char *hex_tag = "0x";
+
+ if (strcspn(buf, hex_tag) == 0) {
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ } else {
+ if (sscanf(buf,"%d",&result)) {
+ return result;
+ }
+ if(sscanf(buf,"-%d",&result)) {
+ return -result;
+ }
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ }
+ return -EBFONT;
+}
+
+
+static int
+sscanf_2_binary(const char *buf) {
+
+ int result = sscanf_2_int(buf);
+
+ if (result < 0){
+ return -EBFONT;
+ }
+ switch (result) {
+ case 0:
+ case 1:
+ return result;
+ default:
+ break;
+ }
+ return -EBFONT;
+}
+
+/* ========== Show functions: For I/O Expander attribute ==========
+ */
+static ssize_t
+_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset),
+ char *buf_p) {
+ size_t len;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ mutex_lock(&ioexp_p->lock);
+ len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset));
+ mutex_unlock(&ioexp_p->lock);
+ return len;
+}
+
+
+static ssize_t
+show_attr_present(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_present,
+ buf_p);
+}
+
+static ssize_t
+show_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_reset,
+ buf_p);
+}
+
+static ssize_t
+show_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_lpmod,
+ buf_p);
+}
+
+
+static ssize_t
+show_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_modsel,
+ buf_p);
+}
+
+/* ========== Store functions: For I/O Expander (R/W) attribute ==========
+ */
+static ssize_t
+_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*set_func)(struct ioexp_obj_s *ioexp_p,
+ int virt_offset, int input_val),
+ const char *buf_p,
+ size_t count) {
+
+ int input, err;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR("%s: data corruption! :%s\n",
+ __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ input = sscanf_2_binary(buf_p);
+ if (input < 0) {
+ return -EBFONT;
+ }
+ mutex_lock(&ioexp_p->lock);
+ err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input);
+ mutex_unlock(&ioexp_p->lock);
+ if (err < 0){
+ return err;
+ }
+ return count;
+}
+
+static ssize_t
+store_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_reset,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_lpmod,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_modsel,
+ buf_p,
+ count);
+}
+
+/* ========== IO Expander attribute: from expander ==========
+ */
+static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL);
+static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset);
+static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod);
+static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel);
+
+/* ========== Functions for module handling ==========
+ */
+static void
+clean_port_obj(void){
+
+ dev_t dev_num;
+ char dev_name[32];
+ struct device *device_p;
+ struct transvr_obj_s *transvr_obj_p;
+ int minor_curr, port_id;
+
+ for (minor_curr=0; minor_curri2c_client_p);
+ kfree(transvr_obj_p);
+ }
+ dev_num = MKDEV(port_major, minor_curr);
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+static int
+get_platform_type(void){
+
+ char log_msg[64] = "ERROR";
+
+ platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL);
+ if (!platform_p){
+ snprintf(log_msg, sizeof(log_msg), "kzalloc fail");
+ goto err_get_platform_type_1;
+ }
+ platform_p->id = PLATFORM_SETTINGS;
+ memset(platform_p->name, 0, sizeof(platform_p->name));
+ snprintf(platform_p->name, (sizeof(platform_p->name) - 1),
+ "%s", platform_map.name);
+ snprintf(log_msg, sizeof(log_msg),
+ "User setup platform: %d (%s)",
+ platform_p->id, platform_p->name);
+ SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return 0;
+
+err_get_platform_type_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return -1;
+}
+
+
+static int
+get_layout_info(void){
+
+ ioexp_layout = redwood_ioexp_layout;
+ port_layout = redwood_port_layout;
+ ioexp_total = ARRAY_SIZE(redwood_ioexp_layout);
+ port_total = ARRAY_SIZE(redwood_port_layout);
+
+ SWPS_INFO("Start to initial platform: %d (%s)\n",
+ platform_p->id, platform_p->name);
+ return 0;
+}
+
+/* ========== Functions for register something ==========
+ */
+
+static int
+register_ioexp_attr_qsfp_1(struct device *device_p){
+ /* Support machine type:
+ * - QSFP : Magnolia, Redwood, Hudson32i
+ * - QSFP+ : Magnolia, Redwood, Hudson32i
+ * - QSFP28: Redwood
+ */
+ char *err_attr = NULL;
+
+ if (device_create_file(device_p, &dev_attr_present) < 0) {
+ err_attr = "dev_attr_present";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_reset) < 0) {
+ err_attr = "dev_attr_reset";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_lpmod) < 0) {
+ err_attr = "dev_attr_lpmod";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_modsel) < 0) {
+ err_attr = "dev_attr_modsel";
+ goto err_ioexp_qsfp1_attr;
+ }
+ return 0;
+
+err_ioexp_qsfp1_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr(struct device *device_p,
+ struct transvr_obj_s *transvr_obj){
+
+ char *err_msg = "ERR";
+
+ switch (transvr_obj->ioexp_obj_p->ioexp_type){
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ if (register_ioexp_attr_qsfp_1(device_p) < 0){
+ err_msg = "register_ioexp_attr_qsfp_1 fail";
+ goto err_reg_ioexp_attr;
+ }
+ break;
+
+ default:
+ err_msg = "Unknow type";
+ goto err_reg_ioexp_attr;
+ }
+ return 0;
+
+err_reg_ioexp_attr:
+ SWPS_ERR("%s: %s :%d \n",
+ __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type);
+ return -1;
+}
+
+
+static int
+register_port_device(char *dev_name,
+ dev_t dev_num,
+ struct transvr_obj_s *transvr_obj){
+
+ struct device *device_p = NULL;
+ device_p = device_create(swp_class_p, /* struct class *cls */
+ NULL, /* struct device *parent */
+ dev_num, /* dev_t devt */
+ transvr_obj, /* void *private_data */
+ dev_name); /* const char *fmt */
+ if (IS_ERR(device_p)){
+ goto err_regswp_create_dev;
+ }
+ if (register_ioexp_attr(device_p, transvr_obj) < 0){
+ goto err_regswp_reg_attr;
+ }
+ return 0;
+
+err_regswp_reg_attr:
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+err_regswp_create_dev:
+ SWPS_ERR("%s fail! :%s\n", __func__, dev_name);
+ return -1;
+}
+
+
+static int
+register_swp_module(void){
+
+ dev_t port_devt = 0;
+ int dev_total = port_total + 1; /* char_dev for module control */
+
+ if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){
+ SWPS_WARN("Allocate PORT MAJOR failure! \n");
+ goto err_register_swp_module_3;
+ }
+ port_major = MAJOR(port_devt);
+
+ /* Create class object */
+ swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME);
+ if (IS_ERR(swp_class_p)) {
+ SWPS_ERR("Create class failure! \n");
+ goto err_register_swp_module_3;
+ }
+ return 0;
+
+err_register_swp_module_3:
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ return -1;
+}
+
+
+/* ========== Module initial relate ==========
+ */
+static int
+create_ioexp_objs(void) {
+
+ int i, run_mod;
+
+ /* Clean IOEXP object */
+ clean_ioexp_objs();
+ /* Get running mode */
+ run_mod = IOEXP_MODE_DIRECT;
+ /* Create IOEXP object */
+ for(i=0; i devlen_max) {
+ snprintf(err_msg, sizeof(err_msg),
+ "SWP_DEV_PORT too long!");
+ goto err_initport_create_tranobj;
+ }
+ memset(dev_name, 0, sizeof(dev_name));
+ snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id);
+ /* Create transceiver object */
+ ioexp_obj_p = get_ioexp_obj(ioexp_id);
+ if (!ioexp_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "IOEXP object:%d not exist", ioexp_id);
+ goto err_initport_create_tranobj;
+ }
+ transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p,
+ ioexp_virt_offset, transvr_type,
+ chipset_type, run_mod);
+ if (!transvr_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "Create transceiver object fail :%s", dev_name);
+ goto err_initport_create_tranobj;
+ }
+ /* Setup Lane_ID mapping */
+ i = ARRAY_SIZE(port_layout[minor_curr].lane_id);
+ j = ARRAY_SIZE(transvr_obj_p->lane_id);
+ if (i != j) {
+ snprintf(err_msg, sizeof(err_msg),
+ "Lane_id size inconsistent %d/%d", i, j);
+ goto err_initport_reg_device;
+ }
+ memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int));
+ /* Create and register device object */
+ if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){
+ snprintf(err_msg, sizeof(err_msg),
+ "register_port_device fail");
+ goto err_initport_reg_device;
+ }
+ /* Setup device_ptr of transvr_obj */
+ dev_p = get_swpdev_by_name(dev_name);
+ if (!dev_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "get_swpdev_by_name fail");
+ goto err_initport_reg_device;
+ }
+ transvr_obj_p->transvr_dev_p = dev_p;
+ /* Success */
+ ok_count++;
+ }
+ SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count);
+ return 0;
+
+err_initport_reg_device:
+ kfree(transvr_obj_p);
+err_initport_create_tranobj:
+ clean_port_obj();
+ SWPS_ERR("%s: %s", __func__, err_msg);
+ SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n",
+ port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod);
+ return -1;
+}
+
+static int __init
+swp_module_init(void){
+
+ if (get_platform_type() < 0){
+ goto err_init_out;
+ }
+ if (get_layout_info() < 0){
+ goto err_init_out;
+ }
+ if (register_swp_module() < 0){
+ goto err_init_out;
+ }
+ if (create_ioexp_objs() < 0){
+ goto err_init_ioexp;
+ }
+ if (create_port_objs() < 0){
+ goto err_init_portobj;
+ }
+ if (init_ioexp_objs() < 0){
+ goto err_init_portobj;
+ }
+ SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION);
+ return 0;
+
+
+err_init_portobj:
+ clean_ioexp_objs();
+err_init_ioexp:
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+err_init_out:
+ SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION);
+ return -1;
+}
+
+
+static void __exit
+swp_module_exit(void){
+ clean_port_obj();
+ clean_ioexp_objs();
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ SWPS_INFO("Remove Inventec switch-port module success.\n");
+}
+
+
+/* Module information */
+MODULE_AUTHOR(SWP_AUTHOR);
+MODULE_DESCRIPTION(SWP_DESC);
+MODULE_VERSION(SWP_VERSION);
+MODULE_LICENSE(SWP_LICENSE);
+
+module_init(swp_module_init);
+module_exit(swp_module_exit);
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h
new file mode 100644
index 000000000000..b186c2202381
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h
@@ -0,0 +1,131 @@
+#ifndef INV_SWPS_H
+#define INV_SWPS_H
+
+#include "transceiver.h"
+#include "io_expander.h"
+
+/* Module settings */
+#define SWP_CLS_NAME "swps"
+#define SWP_DEV_PORT "port"
+#define SWP_AUTOCONFIG_ENABLE (1)
+
+/* Module information */
+#define SWP_AUTHOR "Neil "
+#define SWP_DESC "Inventec port and transceiver driver"
+#define SWP_VERSION "4.2.3"
+#define SWP_LICENSE "GPL"
+
+/* Module status define */
+#define SWP_STATE_NORMAL (0)
+#define SWP_STATE_I2C_DIE (-91)
+
+/* [Note]:
+ * Functions and mechanism for auto-detect platform type is ready,
+ * But HW and BIOS not ready! We need to wait them.
+ * So, please do not use PLATFORM_TYPE_AUTO until they are ready.
+ * (2016.06.13)
+ */
+#define PLATFORM_TYPE_REDWOOD (121)
+/* Current running platfrom */
+#define PLATFORM_SETTINGS PLATFORM_TYPE_REDWOOD
+
+/* Define platform flag and kernel version */
+#if (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD)
+ #define SWPS_KERN_VER_BF_3_8 (1)
+#endif
+
+struct inv_platform_s {
+ int id;
+ char name[64];
+};
+
+struct inv_ioexp_layout_s {
+ int ioexp_id;
+ int ioexp_type;
+ struct ioexp_addr_s addr[4];
+};
+
+struct inv_port_layout_s {
+ int port_id;
+ int chan_id;
+ int ioexp_id;
+ int ioexp_offset;
+ int transvr_type;
+ int chipset_type;
+ int lane_id[8];
+};
+
+/* ==========================================
+ * Inventec Platform Settings
+ * ==========================================
+ */
+struct inv_platform_s platform_map = {PLATFORM_TYPE_REDWOOD, "D7032Q28B" };
+
+/* ==========================================
+ * Redwood Layout configuration
+ * ==========================================
+ */
+struct inv_ioexp_layout_s redwood_ioexp_layout[] = {
+ /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+ {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
+ {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
+ {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
+ },
+ {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
+ {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
+ {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
+ },
+ {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
+ {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
+ {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
+ },
+ {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
+ {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
+ {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
+ },
+};
+
+struct inv_port_layout_s redwood_port_layout[] = {
+ /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+ { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} },
+ { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} },
+ { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} },
+ { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
+ { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
+ { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
+ { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
+ { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
+ { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
+ { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
+ {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
+ {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
+ {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
+ {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
+ {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
+ {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
+ {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
+ {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
+ {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
+ {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
+ {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
+ {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+ {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
+ {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
+ {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+ {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+ {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+ {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+ {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} },
+ {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+ {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} },
+ {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} },
+};
+
+#endif /* INV_SWPS_H */
+
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c
new file mode 100644
index 000000000000..7c9f8a66aec7
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c
@@ -0,0 +1,887 @@
+#include
+#include
+#include
+#include "io_expander.h"
+
+static struct ioexp_obj_s *ioexp_head_p = NULL;
+static struct ioexp_obj_s *ioexp_tail_p = NULL;
+
+struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+/* ========== Private functions ==========
+ */
+int check_channel_tier_1(void);
+
+struct i2c_client *
+_get_i2c_client(struct ioexp_obj_s *self,
+ int chip_id){
+
+ struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p;
+
+ if (!(i2c_curr_p)){
+ SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__);
+ return NULL;
+ }
+ while (i2c_curr_p){
+ if ((i2c_curr_p->chip_id) == chip_id){
+ return i2c_curr_p->i2c_client_p;
+ }
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id);
+ return NULL;
+}
+
+
+static int
+_common_ioexp_update_one(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *ioexp_addr,
+ int chip_id,
+ int data_width,
+ int show_err,
+ char *caller_name) {
+ int buf = 0;
+ int err = 0;
+ int data_id = 0;
+ int r_offset = 0;
+
+ for(data_id=0; data_idread_offset[data_id];
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset);
+ /* Check error */
+ if (buf < 0) {
+ err = 1;
+ if (show_err) {
+ SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf);
+ SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n",
+ ioexp_addr->chan_id, ioexp_addr->chip_addr,
+ ioexp_addr->read_offset[data_id], caller_name);
+ }
+ continue;
+ }
+ /* Update IOEXP object */
+ self->chip_data[chip_id].data[data_id] = (uint8_t)buf;
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+static int
+common_ioexp_update_all(struct ioexp_obj_s *self,
+ int show_err,
+ char *caller_name){
+
+ int err = 0;
+ int chip_id = 0;
+ int chip_amount = self->ioexp_map_p->chip_amount;
+
+ for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]),
+ chip_id,
+ self->ioexp_map_p->data_width,
+ show_err,
+ caller_name) < 0) {
+ err = 1;
+ }
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+static int
+_common_get_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ char *func_mane){
+ uint8_t buf;
+ int err_code;
+
+ /* Get address */
+ err_code = self->fsm_4_direct(self);
+ if (err_code < 0){
+ return err_code;
+ }
+
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Get data form cache */
+ buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ return (int)(buf >> bitmap_obj_p->bit_shift & 0x01);
+}
+
+
+static int
+_common_set_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ int input_val,
+ char *func_mane){
+ int err_code, target_offset;
+ uint8_t origin_byte;
+ uint8_t modify_byte;
+
+ /* Get address */
+ err_code = self->fsm_4_direct(self);
+ if (err_code < 0){
+ return err_code;
+ }
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Prepare write date */
+ origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ switch (input_val) {
+ case 0:
+ modify_byte = origin_byte;
+ SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ case 1:
+ modify_byte = origin_byte;
+ SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ default:
+ SWPS_ERR("Input value incorrect! :%d :%d :%s\n",
+ input_val, self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADINPUT;
+ }
+ /* Setup i2c client */
+ target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset];
+ /* Write byte to chip via I2C */
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id),
+ target_offset,
+ modify_byte);
+ /* Update or bollback object */
+ if (err_code < 0){
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte;
+ SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n",
+ input_val, self->ioexp_id, func_mane, err_code);
+ return err_code;
+ }
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte;
+ return 0;
+}
+
+
+/* ========== Object public functions ==========
+ */
+int
+common_get_present(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ int UNPLUG = 1;
+ int retval = ERR_IOEXP_UNEXCPT;
+
+ retval = _common_get_bit(self,
+ &(self->ioexp_map_p->map_present[virt_offset]),
+ "common_get_present");
+ if (retval < 0) {
+ /* [Note]
+ * => Transceiver object does not need to handle IOEXP layer issues.
+ */
+ return UNPLUG;
+ }
+ return retval;
+}
+
+
+int
+common_get_reset(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ "common_get_reset");
+}
+
+
+int
+common_get_lpmod(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ "common_get_lpmod");
+}
+
+
+int
+common_get_modsel(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ "common_get_modsel");
+}
+
+int
+common_set_reset(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ input_val,
+ "common_set_reset");
+}
+
+
+int
+common_set_lpmod(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ input_val,
+ "common_set_lpmod");
+}
+
+
+int
+common_set_modsel(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ input_val,
+ "common_set_modsel");
+}
+
+int
+ioexp_get_not_support(struct ioexp_obj_s *self,
+ int virt_offset){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+ioexp_set_not_support(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+/* ========== Initial functions for IO Expander ==========
+ */
+int
+common_ioexp_init(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ if (self->mode == IOEXP_MODE_DIRECT) { ///important
+ goto update_common_ioexp_init;
+ }
+ /* Setup default value to each physical IO Expander */
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ /* Get address mapping */
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("%s: IOEXP config incorrect! :%d \n",
+ __func__, chip_id);
+ return -1;
+ }
+ /* Setup default value */
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->write_offset[offset],
+ addr_p->data_default[offset]);
+ if (err_code < 0){
+ SWPS_ERR("%s: set default fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ }
+ }
+
+update_common_ioexp_init:
+ /* Check and update info to object */
+ err_code = self->update_all(self, 1, "common_ioexp_init");
+ if (err_code < 0) {
+ SWPS_ERR("%s: update_all() fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+_is_channel_ready(struct ioexp_obj_s *self){
+
+ int buf = 0;
+ int chip_id = 0; /* Use first chip which be registered */
+ int data_id = 0; /* Use first byte which be registered */
+ struct ioexp_addr_s *ioexp_addr = NULL;
+
+ ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!ioexp_addr){
+ SWPS_ERR("%s: config incorrect!\n", __func__);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id),
+ ioexp_addr->read_offset[data_id]);
+ if (buf >= 0){
+ return 1;
+ }
+ return 0;
+}
+
+int
+_ioexp_init_handler(struct ioexp_obj_s *self){
+
+ int return_val;
+
+ switch (self->mode) {
+ case IOEXP_MODE_DIRECT:
+ return_val = self->init(self);
+ if (return_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ } else {
+ self->state = STATE_IOEXP_NORMAL;
+ }
+ return return_val;
+ default:
+ break;
+ }
+ SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){
+
+ int result_val;
+ int show_err = 1;
+ char *func_mane = "common_ioexp_fsm_4_direct";
+
+ switch (self->state){
+ case STATE_IOEXP_INIT:
+ result_val = _ioexp_init_handler(self);
+ /* Exception case: terminate initial procedure */
+ if(result_val < 0){
+ /* Initial fail */
+ return result_val;
+ }
+ if(self->state == STATE_IOEXP_INIT){
+ /* Keep in INIT state, and return error */
+ return ERR_IOEXP_UNINIT;
+ }
+ /* Case: Initial done */
+ return 0;
+
+ case STATE_IOEXP_NORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ case STATE_IOEXP_ABNORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: Exception occurs :%d\n",
+ __func__, self->state);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+/* ========== Functions for Factory pattern ==========
+ */
+static struct ioexp_map_s *
+get_ioexp_map(int ioexp_type){
+ switch (ioexp_type){
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ return &ioexp_map_redwood_p01p08_p17p24;
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ return &ioexp_map_redwood_p09p16_p25p32;
+ default:
+ return NULL;
+ }
+}
+
+
+int
+setup_ioexp_ssize_attr(struct ioexp_obj_s *self,
+ struct ioexp_map_s *ioexp_map_p,
+ int ioexp_id,
+ int ioexp_type,
+ int run_mode){
+ switch (run_mode){
+ case IOEXP_MODE_DIRECT: /* Direct access device mode */
+ self->mode = run_mode;
+ break;
+ default:
+ SWPS_ERR("%s: non-defined run_mode:%d\n",
+ __func__, run_mode);
+ self->mode = ERR_IOEXP_UNEXCPT;
+ return ERR_IOEXP_UNEXCPT;
+ }
+ self->ioexp_id = ioexp_id;
+ self->ioexp_type = ioexp_type;
+ self->ioexp_map_p = ioexp_map_p;
+ self->state = STATE_IOEXP_INIT;
+ mutex_init(&self->lock);
+ return 0;
+}
+
+
+static int
+setup_addr_mapping(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *addr_map_p){
+ if (!addr_map_p){
+ SWPS_ERR("%s: map is null\n", __func__);
+ return -1;
+ }
+ self->ioexp_map_p->map_addr = addr_map_p;
+ return 0;
+}
+
+
+static int
+setup_ioexp_public_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+ switch (ioexp_type){
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ self->get_present = common_get_present;
+ self->get_reset = common_get_reset;
+ self->get_lpmod = common_get_lpmod;
+ self->get_modsel = common_get_modsel;
+ self->set_reset = common_set_reset;
+ self->set_lpmod = common_set_lpmod;
+ self->set_modsel = common_set_modsel;
+ return 0;
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_ioexp_private_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+
+ switch (ioexp_type){
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ case IOEXP_TYPE_REDWOOD_P09P16:
+
+ self->init = common_ioexp_init;
+ self->update_all = common_ioexp_update_all;
+ self->fsm_4_direct = common_ioexp_fsm_4_direct;
+ return 0;
+
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_i2c_client_one(struct ioexp_obj_s *self,
+ int chip_id){
+
+ char *err_msg = "ERROR";
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client = NULL;
+ struct ioexp_i2c_s *i2c_obj_p = NULL;
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+
+ int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id;
+ adap = i2c_get_adapter(chan_id);
+ if(!adap){
+ err_msg = "Can not get adap!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client){
+ err_msg = "Can not kzalloc client!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL);
+ if (!i2c_obj_p){
+ err_msg = "Can not kzalloc i2c_obj_p!";
+ goto err_ioexp_setup_i2c_2;
+ }
+ client->adapter = adap;
+ client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr;
+ i2c_obj_p->i2c_client_p = client;
+ i2c_obj_p->chip_id = chip_id;
+ i2c_obj_p->next = NULL;
+ if (!self->i2c_head_p){
+ self->i2c_head_p = i2c_obj_p;
+ } else {
+ i2c_curr_p = self->i2c_head_p;
+ while (i2c_curr_p->next){
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ i2c_curr_p->next = i2c_obj_p;
+ }
+ return 0;
+
+err_ioexp_setup_i2c_2:
+ kfree(client);
+err_ioexp_setup_i2c_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id);
+ return -1;
+}
+
+
+static int
+setup_i2c_client(struct ioexp_obj_s* self){
+
+ int result;
+ int chip_id = 0;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ result = setup_i2c_client_one(self, chip_id);
+ if (result < 0){
+ SWPS_ERR("%s fail! :%d\n", __func__, chip_id);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+setup_ioexp_config(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id);
+ return -1;
+ }
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->conf_offset[offset],
+ addr_p->conf_default[offset]);
+
+ if (err_code < 0){
+ SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code);
+ return -2;
+ }
+ }
+ }
+ return 0;
+}
+
+struct ioexp_obj_s *
+_create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_map_s* ioexp_map_p;
+ struct ioexp_obj_s* result_p;
+ struct ioexp_i2c_s *i2c_curr_p;
+ struct ioexp_i2c_s *i2c_next_p;
+
+ /* Get layout */
+ ioexp_map_p = get_ioexp_map(ioexp_type);
+ if (!ioexp_map_p){
+ SWPS_ERR("%s: Invalid ioexp_type\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare IOEXP object */
+ result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+ if (!result_p){
+ SWPS_ERR("%s: kzalloc failure!\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare static size attributes */
+ if (setup_ioexp_ssize_attr(result_p,
+ ioexp_map_p,
+ ioexp_id,
+ ioexp_type,
+ run_mode) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ /* Prepare address mapping */
+ if (setup_addr_mapping(result_p, addr_map_p) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ if (setup_i2c_client(result_p) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ /* Prepare call back functions of object */
+ if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ return result_p;
+
+err_create_ioexp_setup_i2c_fail:
+ i2c_curr_p = result_p->i2c_head_p;
+ i2c_next_p = result_p->i2c_head_p;
+ while (i2c_curr_p){
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+err_create_ioexp_setup_attr_fail:
+ kfree(result_p);
+err_create_ioexp_fail:
+ SWPS_ERR("%s: fail! :%d :%d \n",
+ __func__, ioexp_id, ioexp_type);
+ return NULL;
+}
+
+
+int
+create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_obj_s *ioexp_p = NULL;
+
+ ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type,
+ addr_map_p, run_mode);
+ if (!ioexp_p){
+ return -1;
+ }
+ if (ioexp_head_p == NULL){
+ ioexp_head_p = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+ }
+ ioexp_tail_p->next = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+}
+
+static int
+_init_ioexp_obj(struct ioexp_obj_s* self) {
+
+ char *err_msg = "ERR";
+ char *func_name = "_init_ioexp_obj";
+
+ /* Setup IOEXP configure byte */
+ if (setup_ioexp_config(self) < 0){
+ err_msg = "setup_ioexp_config fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Setup default data */
+ if (_ioexp_init_handler(self) < 0){
+ err_msg = "_ioexp_init_handler fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Update all */
+ if (self->state == STATE_IOEXP_NORMAL){
+ if (self->update_all(self, 1, func_name) < 0){
+ err_msg = "update_all() fail";
+ goto err_init_ioexp_obj;
+ }
+ }
+ return 0;
+
+err_init_ioexp_obj:
+ SWPS_DEBUG("%s: %s\n", __func__, err_msg);
+ return -1;
+}
+
+int
+init_ioexp_objs(void){
+ /* Return value:
+ * 0: Success
+ * -1: Detect topology error
+ * -2: SWPS internal error
+ */
+
+ struct ioexp_obj_s *curr_p = ioexp_head_p;
+
+ if (!curr_p) {
+ SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__);
+ return -2;
+ }
+ while (curr_p) {
+ if (_init_ioexp_obj(curr_p) < 0) {
+ SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__);
+ return -1;
+ }
+ curr_p = curr_p->next;
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+ return 0;
+}
+
+void
+clean_ioexp_objs(void){
+
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+ struct ioexp_i2c_s *i2c_next_p = NULL;
+ struct ioexp_obj_s *ioexp_next_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ if (ioexp_head_p == NULL){
+ ioexp_tail_p = NULL;
+ return;
+ }
+ while(ioexp_curr_p){
+ ioexp_next_p = ioexp_curr_p->next;
+ i2c_curr_p = ioexp_curr_p->i2c_head_p;
+ while (i2c_curr_p) {
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+ kfree(ioexp_curr_p);
+ ioexp_curr_p = ioexp_next_p;
+ }
+ ioexp_tail_p = NULL;
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+struct ioexp_obj_s *
+get_ioexp_obj(int ioexp_id){
+
+ struct ioexp_obj_s *result_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while(ioexp_curr_p){
+ if (ioexp_curr_p->ioexp_id == ioexp_id){
+ result_p = ioexp_curr_p;
+ break;
+ }
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return result_p;
+}
+int
+check_channel_tier_1(void) {
+
+ if ( (!_is_channel_ready(ioexp_head_p)) &&
+ (!_is_channel_ready(ioexp_tail_p)) ){
+ return -1;
+ }
+ return 0;
+}
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h
new file mode 100644
index 000000000000..8c51b4f6d94f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h
@@ -0,0 +1,136 @@
+#ifndef IO_EXPANDER_H
+#define IO_EXPANDER_H
+
+#include
+
+/* IOEXP type define (QSFP series) */
+#define IOEXP_TYPE_REDWOOD_P01P08 (10202)
+#define IOEXP_TYPE_REDWOOD_P09P16 (10203)
+
+/* IOEXP mode define */
+#define IOEXP_MODE_DIRECT (19001)
+
+/* IOEXP state define */
+#define STATE_IOEXP_NORMAL (0)
+#define STATE_IOEXP_INIT (-1)
+#define STATE_IOEXP_ABNORMAL (-2)
+
+/* IOEXP error code define */
+#define ERR_IOEXP_NOTSUPPORT (-100)
+#define ERR_IOEXP_UNINIT (-101)
+#define ERR_IOEXP_BADCONF (-102)
+#define ERR_IOEXP_BADINPUT (-105)
+#define ERR_IOEXP_UNEXCPT (-199)
+
+
+#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
+#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
+#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args)
+
+#ifdef DEBUG_SWPS
+# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args)
+#else
+# define SWPS_DEBUG(fmt, args...)
+#endif
+
+
+struct ioexp_addr_s {
+ int chan_id;
+ int chip_addr;
+ int read_offset[8];
+ int write_offset[8];
+ int conf_offset[8];
+ uint8_t data_default[8];
+ uint8_t conf_default[8];
+};
+
+struct ioexp_i2c_s {
+ int chip_id;
+ struct i2c_client *i2c_client_p;
+ struct ioexp_i2c_s *next;
+};
+
+
+struct ioexp_bitmap_s {
+ int chip_id; /* IOEXP chip id */
+ int ioexp_voffset; /* IOEXP virtual offset */
+ int bit_shift;
+};
+
+struct ioexp_map_s {
+ int chip_amount; /* Number of chips that IOEXP object content */
+ int data_width; /* Number of (Read/Write/Config) bytes */
+ struct ioexp_addr_s *map_addr; /* Chip address info */
+ struct ioexp_bitmap_s map_present[8]; /* IOEXP for SFP / QSFP */
+ struct ioexp_bitmap_s map_reset[8]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_lpmod[8]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_modsel[8]; /* IOEXP for QSFP */
+};
+
+struct ioexp_data_s {
+ uint8_t data[8];
+};
+
+struct ioexp_obj_s {
+
+ /* ============================
+ * Object public property
+ * ============================
+ */
+ int ioexp_id;
+ int ioexp_type;
+
+ /* ============================
+ * Object private property
+ * ============================
+ */
+ struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
+ struct ioexp_map_s *ioexp_map_p;
+ struct ioexp_obj_s *next;
+ struct ioexp_i2c_s *i2c_head_p;
+ struct mutex lock;
+ int mode;
+ int state;
+
+ /* ===========================================
+ * Object public functions
+ * ===========================================
+ */
+ int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
+ int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+
+ /* ===========================================
+ * Object private functions
+ * ===========================================
+ */
+ int (*init)(struct ioexp_obj_s *self);
+ int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
+ int (*fsm_4_direct)(struct ioexp_obj_s* self);
+};
+
+
+struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
+int create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode);
+int init_ioexp_objs(void);
+void clean_ioexp_objs(void);
+
+int check_channel_tier_1(void);
+
+/* Macro for bit control */
+#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift)))
+#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
+
+
+#endif /* IO_EXPANDER_H */
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c
new file mode 100644
index 000000000000..36ccc45a9216
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c
@@ -0,0 +1,898 @@
+#include
+#include
+#include
+#include
+#include "io_expander.h"
+#include "transceiver.h"
+
+
+/* ========== Register EEPROM address mapping ==========
+ */
+struct eeprom_map_s eeprom_map_qsfp = {
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+};
+
+struct eeprom_map_s eeprom_map_qsfp28 = {
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+};
+
+
+/* ========== Utility Functions ==========
+ */
+void
+alarm_msg_2_user(struct transvr_obj_s *self,
+ char *emsg) {
+
+ SWPS_ERR("%s on %s.\n", emsg, self->swp_name);
+}
+
+
+/* ========== Private functions ==========
+ */
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self);
+
+static void
+_transvr_clean_retry(struct transvr_obj_s *self) {
+ self->retry = 0;
+}
+
+
+static int
+_transvr_handle_retry(struct transvr_obj_s *self, int retry) {
+ /* Return: 0: keep retry
+ * -1: stop retry
+ */
+ if (self->retry == 0) {
+ self->retry = retry;
+ }
+ self->retry -= 1;
+ if (self->retry <= 0) {
+ _transvr_clean_retry(self);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_common_setup_page(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ int show_e) {
+ /* return:
+ * 0 : OK
+ * -1 : EEPROM settings incorrect
+ * -2 : I2C R/W failure
+ * -3 : Undefined case
+ */
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Check */
+ if ((addr < 0) || (offset < 0) || (len < 0)) {
+ emsg = "EEPROM settings incorrect";
+ retval = -1;
+ goto err_common_setup_page;
+ }
+ /* Case1: continue access */
+ if ((self->i2c_client_p->addr == addr) &&
+ (self->curr_page == page)) {
+ return 0;
+ }
+ self->i2c_client_p->addr = addr;
+ /* Case2: select lower page */
+ if (page == -1) {
+ self->curr_page = page;
+ return 0;
+ }
+ /* Case3: select upper page */
+ if (page >= 0) {
+ goto upper_common_setup_page;
+ }
+ /* Unexpected case */
+ show_e = 1;
+ emsg = "Unexpected case";
+ retval = -3;
+ goto err_common_setup_page;
+
+upper_common_setup_page:
+ if (i2c_smbus_write_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_PAGE_SELECT_OFFSET,
+ page) < 0) {
+ emsg = "I2C R/W failure";
+ retval = -2;
+ goto err_common_setup_page;
+ }
+ self->curr_page = page;
+ mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY);
+ return 0;
+
+err_common_setup_page:
+ if (show_e) {
+ SWPS_INFO("%s: %s", __func__, emsg);
+ SWPS_INFO("%s: :0x%02x :%d :%d :%d\n",
+ __func__, addr, page, offset, len);
+ }
+ return retval;
+}
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+is_plugged(struct transvr_obj_s *self){
+
+ int limit = 63;
+ int present = DEBUG_TRANSVR_INT_VAL;
+ char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+ struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ snprintf(emsg, limit, "ioexp_p is null!");
+ goto err_is_plugged_1;
+ }
+ present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset);
+ switch (present){
+ case 0:
+ return 1;
+ case 1:
+ return 0;
+ case ERR_IOEXP_UNINIT:
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ default:
+ if (ioexp_p->state == STATE_IOEXP_INIT){
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ }
+ break;
+ }
+ SWPS_INFO("%s: Exception case! :%d :%d\n",
+ __func__, present, ioexp_p->state);
+ return 0;
+
+err_is_plugged_1:
+ SWPS_DEBUG("%s: %s\n", __func__, emsg);
+ return 0;
+}
+
+
+static int
+detect_transvr_type(struct transvr_obj_s* self){
+
+ int type = TRANSVR_TYPE_ERROR;
+
+ self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+ type = i2c_smbus_read_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_COMID_OFFSET);
+
+ /* Case: 1. Wait transceiver I2C module.
+ * 2. Transceiver I2C module failure.
+ * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there
+ * are exist some case that we need to wait transceiver.
+ * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than
+ * state machine will keep trace with it.
+ * 2. There exist some I2C failure case we need to handle. Such as user
+ * insert the failure transceiver, or any reason cause it abnormal.
+ */
+ if (type < 0){
+ switch (type) {
+ case -EIO:
+ SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n",
+ __func__, self->swp_name);
+ return TRANSVR_TYPE_UNPLUGGED;
+ case -ENXIO:
+ SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n",
+ __func__, self->swp_name);
+ return TRANSVR_TYPE_UNPLUGGED;
+ default:
+ break;
+ }
+ SWPS_INFO("%s: %s unexpected smbus return:%d \n",
+ __func__, self->swp_name, type);
+ return TRANSVR_TYPE_ERROR;
+ }
+ /* Identify valid transceiver type */
+ switch (type){
+ case TRANSVR_TYPE_SFP:
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ case TRANSVR_TYPE_QSFP_28:
+ break;
+ case TRANSVR_TYPE_UNKNOW_1:
+ case TRANSVR_TYPE_UNKNOW_2:
+ type = TRANSVR_TYPE_UNKNOW_2;
+ break;
+ default:
+ SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type);
+ type = TRANSVR_TYPE_ERROR;
+ break;
+ }
+ return type;
+}
+
+
+static int
+detect_transvr_state(struct transvr_obj_s *self,
+ int result[2]){
+ /* [return] [result-0] [result-1]
+ * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE
+ * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED
+ * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR
+ * 0 STATE_TRANSVR_INIT /
+ * 0 STATE_TRANSVR_SWAPPED
+ * 0 STATE_TRANSVR_CONNECTED
+ * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR
+ * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR
+ * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2
+ */
+ result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */
+ result[1] = TRANSVR_TYPE_ERROR; /* For return type */
+
+ /* Case1: Fake type */
+ if (self->type == TRANSVR_TYPE_FAKE){
+ result[0] = STATE_TRANSVR_CONNECTED;
+ result[1] = TRANSVR_TYPE_FAKE;
+ return 0;
+ }
+ /* Case2: Transceiver unplugged */
+ if (!is_plugged(self)){
+ result[0] = STATE_TRANSVR_DISCONNECTED;
+ result[1] = TRANSVR_TYPE_UNPLUGGED;
+ return 0;
+ }
+ /* Case3: Transceiver be isolated */
+ if (self->state == STATE_TRANSVR_ISOLATED){
+ result[0] = STATE_TRANSVR_ISOLATED;
+ result[1] = TRANSVR_TYPE_ERROR;
+ return ERR_TRNASVR_BE_ISOLATED;
+ }
+ /* Case4: Transceiver plugged */
+ result[1] = detect_transvr_type(self);
+ /* Case4.1: I2C topology crash
+ * Note : There are some I2C issues cause by transceiver/cables.
+ * We need to check topology status when user insert it.
+ * But in this step, we can't not ensure this is the issues
+ * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper
+ * layer will diagnostic I2C topology.
+ */
+ if (check_channel_tier_1() < 0) {
+ SWPS_INFO("%s: %s detect I2C crash :%d\n",
+ __func__, self->swp_name, self->state);
+ result[0] = STATE_TRANSVR_UNEXCEPTED;
+ result[1] = TRANSVR_TYPE_ERROR;
+ return ERR_TRANSVR_I2C_CRASH;
+ }
+ /* Case4.2: System initial not ready,
+ * Note : Sometime i2c channel or transceiver EEPROM will delay that will
+ * cause system in inconsistent state between EEPROM and IOEXP.
+ * In this case, SWP transceiver object keep state at LINK_DOWN
+ * to wait system ready.
+ * By the way, State Machine will handle these case.
+ */
+ if (result[1] == TRANSVR_TYPE_UNPLUGGED){
+ result[0] = STATE_TRANSVR_DISCONNECTED;
+ return 0;
+ }
+ /* Case4.3: Error transceiver type */
+ if (result[1] == TRANSVR_TYPE_ERROR){
+ result[0] = STATE_TRANSVR_ISOLATED;
+ SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name);
+ alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!");
+ return ERR_TRNASVR_BE_ISOLATED;
+ }
+ /* Case3.3: Unknow transceiver type */
+ if ((result[1] == TRANSVR_TYPE_UNKNOW_1) ||
+ (result[1] == TRANSVR_TYPE_UNKNOW_2) ){
+ result[0] = STATE_TRANSVR_UNEXCEPTED;
+ return ERR_TRANSVR_UNEXCPT;
+ }
+ /* Case3.4: During initial process */
+ if (self->state == STATE_TRANSVR_INIT){
+ result[0] = STATE_TRANSVR_INIT;
+ return 0;
+ }
+ /* Case3.5: Transceiver be swapped */
+ if (self->type != result[1]){
+ result[0] = STATE_TRANSVR_SWAPPED;
+ return 0;
+ }
+ /* Case3.6: Link up state */
+ result[0] = STATE_TRANSVR_CONNECTED;
+ return 0;
+}
+int
+common_fsm_4_direct_mode(struct transvr_obj_s* self,
+ char *caller_name){
+
+ int err;
+ int detect_result[2];
+ int current_state = STATE_TRANSVR_UNEXCEPTED;
+ int current_type = TRANSVR_TYPE_ERROR;
+
+ if (self->state == STATE_TRANSVR_NEW) {
+ if (_transvr_init_handler(self) < 0){
+ return ERR_TRANSVR_INIT_FAIL;
+ }
+ }
+ err = detect_transvr_state(self, detect_result);
+ if (err < 0) {
+ return err;
+ }
+ /* In Direct mode, driver only detect transceiver when user call driver interface
+ * which on sysfs. So it only need consider the state of Transceiver.
+ */
+ current_state = detect_result[0];
+ current_type = detect_result[1];
+
+ switch (current_state){
+
+ case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */
+ self->state = current_state;
+ self->type = current_type;
+ return ERR_TRANSVR_UNPLUGGED;
+
+ case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */
+ return ERR_TRANSVR_UNINIT;
+
+ case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */
+ return ERR_TRNASVR_BE_ISOLATED;
+
+ case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */
+ self->state = current_state;
+ self->type = current_type;
+ return 0;
+
+ case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */
+ self->type = current_type;
+ if (reload_transvr_obj(self, current_type) < 0){
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ return ERR_TRANSVR_UNEXCPT;
+ }
+ self->state = current_state;
+ return 0;
+
+ case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ self->type = TRANSVR_TYPE_ERROR;
+ return ERR_TRANSVR_UNEXCPT;
+
+ default:
+ SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state);
+ break;
+ }
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+int
+fake_fsm_4_direct_mode(struct transvr_obj_s* self,
+ char *caller_name){
+ self->state = STATE_TRANSVR_CONNECTED;
+ self->type = TRANSVR_TYPE_FAKE;
+ return 0;
+}
+
+/* ========== Object Initial handler ==========
+ */
+static int
+_is_transvr_valid(struct transvr_obj_s *self,
+ int type,
+ int state) {
+ /* [Return]
+ * 0 : OK, inserted
+ * EVENT_TRANSVR_INIT_DOWN : OK, removed
+ * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported
+ * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined
+ */
+ switch (type) {
+ case TRANSVR_TYPE_SFP:
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ case TRANSVR_TYPE_QSFP_28:
+ case TRANSVR_TYPE_UNPLUGGED:
+ case TRANSVR_TYPE_FAKE:
+ break;
+ default:
+ SWPS_INFO("detect undefined type:0x%02x on %s\n",
+ type, self->swp_name);
+ return EVENT_TRANSVR_INIT_FAIL;
+ }
+ switch (state) {
+ case STATE_TRANSVR_DISCONNECTED:
+ return EVENT_TRANSVR_INIT_DOWN;
+ case STATE_TRANSVR_INIT:
+ case STATE_TRANSVR_CONNECTED:
+ case STATE_TRANSVR_SWAPPED:
+ break;
+ default:
+ SWPS_INFO("detect undefined state:%d on %s\n",
+ state, self->swp_name);
+ return EVENT_TRANSVR_EXCEP_INIT;
+ }
+ return 0;
+}
+
+
+static int
+_is_transvr_hw_ready(struct transvr_obj_s *self,
+ int type){
+ /* [Return]
+ * EVENT_TRANSVR_TASK_DONE : Ready
+ * EVENT_TRANSVR_TASK_WAIT : Not ready
+ * EVENT_TRANSVR_INIT_FAIL : Error
+ */
+ int addr = DEBUG_TRANSVR_INT_VAL;
+ int page = DEBUG_TRANSVR_INT_VAL;
+ int offs = DEBUG_TRANSVR_INT_VAL;
+ int bit = DEBUG_TRANSVR_INT_VAL;
+ int ready = DEBUG_TRANSVR_INT_VAL;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL;
+
+ switch (type) {
+ case TRANSVR_TYPE_SFP:
+ addr = VAL_TRANSVR_8472_READY_ADDR;
+ page = VAL_TRANSVR_8472_READY_PAGE;
+ offs = VAL_TRANSVR_8472_READY_OFFSET;
+ bit = VAL_TRANSVR_8472_READY_BIT;
+ ready = VAL_TRANSVR_8472_READY_VALUE;
+ ab_val = VAL_TRANSVR_8472_READY_ABNORMAL;
+ break;
+
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ case TRANSVR_TYPE_QSFP_28:
+ addr = VAL_TRANSVR_8436_READY_ADDR;
+ page = VAL_TRANSVR_8436_READY_PAGE;
+ offs = VAL_TRANSVR_8436_READY_OFFSET;
+ bit = VAL_TRANSVR_8436_READY_BIT;
+ ready = VAL_TRANSVR_8436_READY_VALUE;
+ ab_val = VAL_TRANSVR_8436_READY_ABNORMAL;
+ break;
+
+ case TRANSVR_TYPE_UNPLUGGED:
+ case TRANSVR_TYPE_FAKE:
+ return EVENT_TRANSVR_TASK_DONE;
+
+ default:
+ emsg = "unexpected case";
+ goto err_is_transvr_hw_ready;
+ }
+ /* Select target page */
+ err = _common_setup_page(self, addr, page, offs, 1, 0);
+ if (err < 0) {
+ emsg = "setup page fail";
+ goto err_is_transvr_hw_ready;
+ }
+ /* Check feature supported
+ * [Note]
+ * Some of transceiver/cables doesn't support "Status Indicators"
+ * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the
+ * step of checking Status Indicators, then state machine will take
+ * the following handle procedure.
+ */
+ err = i2c_smbus_read_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_COMID_OFFSET);
+ if (err < 0) {
+ emsg = "doesn't support Status Indicators";
+ goto bypass_is_transvr_hw_ready;
+ }
+ /* Filter abnormal case */
+ if (err == ab_val) {
+ emsg = "detect using unusual definition.";
+ goto bypass_is_transvr_hw_ready;
+ }
+ /* Get Status Indicators */
+ err = i2c_smbus_read_byte_data(self->i2c_client_p, offs);
+ if (err < 0) {
+ emsg = "detect current value fail";
+ goto err_is_transvr_hw_ready;
+ }
+ if ((err & (1<:%d\n", __func__, emsg, type);
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_is_transvr_hw_ready:
+ SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type);
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self){
+
+ int detect[2];
+ int d_state = STATE_TRANSVR_UNEXCEPTED;
+ int d_type = TRANSVR_TYPE_ERROR;
+ int result = ERR_TRANSVR_UNINIT;
+ int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */
+ int elimit = 63;
+ char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ /* Clean and check callback */
+ self->state = STATE_TRANSVR_INIT;
+ if (self->init == NULL) {
+ snprintf(emsg, elimit, "init() is null");
+ goto initer_err_case_unexcept_0;
+ }
+ /* Detect transceiver information */
+ result = detect_transvr_state(self, detect);
+ if (result < 0) {
+ snprintf(emsg, elimit, "detect_transvr_state() fail");
+ switch (result) {
+ case ERR_TRANSVR_I2C_CRASH:
+ goto initer_err_case_i2c_ceash;
+ case ERR_TRNASVR_BE_ISOLATED:
+ goto initer_err_case_be_isolated;
+
+ case ERR_TRANSVR_UNEXCPT:
+ default:
+ break;
+ }
+ goto initer_err_case_retry_1;
+ }
+ d_state = detect[0];
+ d_type = detect[1];
+
+ /* Verify transceiver type and state */
+ switch (_is_transvr_valid(self, d_type, d_state)) {
+ case 0:
+ break;
+ case EVENT_TRANSVR_INIT_DOWN:
+ goto initer_ok_case_down;;
+ case EVENT_TRANSVR_INIT_FAIL:
+ snprintf(emsg, elimit, "transceiver type doesn't support");
+ goto initer_err_case_alarm_to_user;
+ case EVENT_TRANSVR_EXCEP_INIT:
+ default:
+ goto initer_err_case_unexcept_0;
+ }
+
+ /* Handle reload case */
+ if (self->type != d_type){
+ /* This is the protect mechanism. Normally, This case will not happen.
+ * When State machine detect swap event during initial, It will trigger
+ * reload function to ensure type correct. */
+ if (_reload_transvr_obj(self, d_type) < 0){
+ snprintf(emsg, elimit, "reload object fail");
+ goto initer_err_case_unexcept_0;
+ }
+ }
+
+ /* Check transceiver HW initial ready */
+ switch (_is_transvr_hw_ready(self, d_type)) {
+ case EVENT_TRANSVR_TASK_DONE:
+ break;
+ case EVENT_TRANSVR_TASK_WAIT:
+ goto initer_err_case_retry_1;
+ case EVENT_TRANSVR_INIT_FAIL:
+ default:
+ goto initer_err_case_unexcept_0;
+ }
+
+ /* Try to update all and check */
+ if (self->update_all(self, 1) < 0){
+ /* For some transceiver, EEPROME has lag issues during initial stage.
+ * In this case, we set status back to STATE_TRANSVR_NEW, than it will
+ * be checked in next polling cycle. */
+ goto initer_err_case_retry_1;
+ }
+
+ /* Execute init() call back */
+ result = self->init(self);
+ switch (result) {
+ case EVENT_TRANSVR_TASK_DONE:
+ break;
+ case EVENT_TRANSVR_TASK_WAIT:
+ goto initer_ok_case_wait;
+
+ default:
+ snprintf(emsg, elimit, "undefined init() return:%d\n", result);
+ goto initer_err_case_unexcept_0;
+ }
+ goto initer_ok_case_up;
+
+
+initer_ok_case_wait:
+ return EVENT_TRANSVR_TASK_WAIT;
+
+initer_ok_case_up:
+ self->state = STATE_TRANSVR_CONNECTED;
+ self->temp = 0;
+ return EVENT_TRANSVR_INIT_UP;
+
+initer_ok_case_down:
+ self->temp = 0;
+ self->state = STATE_TRANSVR_DISCONNECTED;
+ return EVENT_TRANSVR_INIT_DOWN;
+
+initer_err_case_i2c_ceash:
+ SWPS_DEBUG("%s: %s :%s :I2C crash\n",
+ __func__, emsg, self->swp_name);
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ return EVENT_TRANSVR_I2C_CRASH;
+
+initer_err_case_be_isolated:
+ SWPS_DEBUG("%s: %s :%s :isolated\n",
+ __func__, emsg, self->swp_name);
+ self->state = STATE_TRANSVR_ISOLATED;
+ return EVENT_TRANSVR_EXCEP_ISOLATED;
+
+initer_err_case_retry_1:
+ SWPS_DEBUG("%s: %s :%s :retry\n",
+ __func__, emsg, self->swp_name);
+ if (_transvr_handle_retry(self, retry) == 0) {
+ self->state = STATE_TRANSVR_NEW;
+ return EVENT_TRANSVR_INIT_REINIT;
+ }
+ goto initer_err_case_alarm_to_user;
+
+initer_err_case_unexcept_0:
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ return EVENT_TRANSVR_INIT_FAIL;
+
+initer_err_case_alarm_to_user:
+ SWPS_DEBUG("%s: %s :%s :alarm_to_user\n",
+ __func__, emsg, self->swp_name);
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard");
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+static int
+setup_transvr_private_cb(struct transvr_obj_s *self,
+ int transvr_type){
+ switch (transvr_type){
+ case TRANSVR_TYPE_SFP:
+ self->fsm_4_direct = common_fsm_4_direct_mode;
+ return 0;
+
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ self->fsm_4_direct = common_fsm_4_direct_mode;
+ return 0;
+
+ case TRANSVR_TYPE_QSFP_28:
+ self->fsm_4_direct = common_fsm_4_direct_mode;
+ return 0;
+
+ case TRANSVR_TYPE_FAKE:
+ self->fsm_4_direct = fake_fsm_4_direct_mode;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type);
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static struct eeprom_map_s *
+get_eeprom_map(int transvr_type){
+
+ switch (transvr_type){
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ return &eeprom_map_qsfp;
+ case TRANSVR_TYPE_QSFP_28:
+ return &eeprom_map_qsfp28;
+
+ default:
+ break;
+ }
+ SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type);
+ return NULL;
+}
+
+
+static int
+setup_transvr_ssize_attr(char *swp_name,
+ struct transvr_obj_s *self,
+ struct eeprom_map_s *map_p,
+ struct ioexp_obj_s *ioexp_obj_p,
+ int ioexp_virt_offset,
+ int transvr_type,
+ int chipset_type,
+ int chan_id,
+ int run_mode){
+ switch (run_mode){
+ case TRANSVR_MODE_DIRECT: /* Direct access device mode */
+ self->mode = run_mode;
+ break;
+ default:
+ SWPS_ERR("%s: non-defined run_mode:%d\n",
+ __func__, run_mode);
+ self->mode = DEBUG_TRANSVR_INT_VAL;
+ return -1;
+ }
+ self->eeprom_map_p = map_p;
+ self->ioexp_obj_p = ioexp_obj_p;
+ self->ioexp_virt_offset = ioexp_virt_offset;
+ self->chan_id = chan_id;
+ self->layout = transvr_type;
+ self->type = transvr_type;
+ self->chipset_type = chipset_type;
+ self->state = STATE_TRANSVR_NEW;
+ self->info = STATE_TRANSVR_NEW;
+ self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE;
+ strncpy(self->swp_name, swp_name, 32);
+ mutex_init(&self->lock);
+ return 0;
+}
+
+
+
+static int
+setup_i2c_client(struct transvr_obj_s *self){
+
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client = NULL;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ adap = i2c_get_adapter(self->chan_id);
+ if(!adap){
+ snprintf(err_msg, sizeof(err_msg),
+ "can not get adap:%d", self->chan_id);
+ goto err_setup_i2c_client;
+ }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client){
+ snprintf(err_msg, sizeof(err_msg),
+ "can not kzalloc client:%d", self->chan_id);
+ goto err_setup_i2c_client;
+ }
+ client->adapter = adap;
+ self->i2c_client_p = client;
+ self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+ return 0;
+
+err_setup_i2c_client:
+ SWPS_ERR("%s: %s\n", __func__, err_msg);
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+
+struct transvr_obj_s *
+create_transvr_obj(char *swp_name,
+ int chan_id,
+ struct ioexp_obj_s *ioexp_obj_p,
+ int ioexp_virt_offset,
+ int transvr_type,
+ int chipset_type,
+ int run_mode){
+
+ struct transvr_obj_s *result_p;
+ struct eeprom_map_s *map_p;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ /* Allocate transceiver object */
+ map_p = get_eeprom_map(transvr_type);
+ if (!map_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "Invalid transvr_type:%d", transvr_type);
+ goto err_create_transvr_fail;
+ }
+ result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+ if (!result_p){
+ snprintf(err_msg, sizeof(err_msg), "kzalloc fail");
+ goto err_create_transvr_fail;
+ }
+ /* Prepare static size attributes */
+ if (setup_transvr_ssize_attr(swp_name,
+ result_p,
+ map_p,
+ ioexp_obj_p,
+ ioexp_virt_offset,
+ transvr_type,
+ chipset_type,
+ chan_id,
+ run_mode) < 0){
+ goto err_create_transvr_sattr_fail;
+ }
+
+ /* Prepare call back functions of object */
+ if (setup_transvr_private_cb(result_p, transvr_type) < 0){
+ goto err_create_transvr_sattr_fail;
+ }
+ /* Prepare i2c client object */
+ if (setup_i2c_client(result_p) < 0){
+ goto err_create_transvr_sattr_fail;
+ }
+ return result_p;
+err_create_transvr_sattr_fail:
+ kfree(result_p);
+err_create_transvr_fail:
+ SWPS_ERR("%s: %s :%d :%d :%d\n",
+ __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type);
+ return NULL;
+}
+
+
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,
+ int new_type){
+
+ struct eeprom_map_s *new_map_p;
+ struct eeprom_map_s *old_map_p = self->eeprom_map_p;
+ struct i2c_client *old_i2c_p = self->i2c_client_p;
+ int old_type = self->type;
+
+ /* Change state to STATE_TRANSVR_INIT */
+ self->state = STATE_TRANSVR_INIT;
+ self->type = new_type;
+ /* Replace EEPROME map */
+ new_map_p = get_eeprom_map(new_type);
+ if (!new_map_p){
+ goto err_private_reload_func_1;
+ }
+ self->eeprom_map_p = new_map_p;
+ /* Reload i2c client */
+ if (setup_i2c_client(self) < 0){
+ goto err_private_reload_func_2;
+ }
+ if (setup_transvr_private_cb(self, new_type) < 0){
+ goto err_private_reload_func_3;
+ }
+ kfree(old_i2c_p);
+ return 0;
+
+err_private_reload_func_3:
+ SWPS_INFO("%s: init() fail!\n", __func__);
+ kfree(old_i2c_p);
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ self->type = TRANSVR_TYPE_ERROR;
+ return -2;
+
+err_private_reload_func_2:
+ self->eeprom_map_p = old_map_p;
+ self->i2c_client_p = old_i2c_p;
+err_private_reload_func_1:
+ self->state = STATE_TRANSVR_UNEXCEPTED;
+ self->type = old_type;
+ SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type);
+ return -1;
+}
+
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,
+ int new_type){
+
+ int result_val = ERR_TRANSVR_UNEXCPT;
+
+ /* Reload phase */
+ result_val = _reload_transvr_obj(self, new_type);
+ if (result_val < 0){
+ SWPS_INFO("%s: reload phase fail! :%d\n",
+ __func__, result_val);
+ return EVENT_TRANSVR_RELOAD_FAIL;
+ }
+ /* Initial phase */
+ result_val = _transvr_init_handler(self);
+ if (result_val < 0){
+ SWPS_INFO("%s: initial phase fail! :%d\n",
+ __func__, result_val);
+ }
+ return result_val;
+}
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h
new file mode 100644
index 000000000000..487fcdd76773
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h
@@ -0,0 +1,167 @@
+#ifndef TRANSCEIVER_H
+#define TRANSCEIVER_H
+
+#include
+
+/* Transceiver type define */
+#define TRANSVR_TYPE_UNKNOW_1 (0x00)
+#define TRANSVR_TYPE_UNKNOW_2 (0xff)
+#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */
+#define TRANSVR_TYPE_QSFP (0x0c)
+#define TRANSVR_TYPE_QSFP_PLUS (0x0d)
+#define TRANSVR_TYPE_QSFP_28 (0x11)
+#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */
+#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */
+#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */
+#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */
+
+/* Transceiver mode define */
+#define TRANSVR_MODE_DIRECT (21000)
+
+/* Transceiver state define
+ * [Note]
+ * 1. State is used to represent the state of "Transceiver" and "Object".
+ * 2. State for different target has different means. The description as following:
+ */
+#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */
+#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */
+#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */
+#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */
+#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */
+#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */
+#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */
+
+/* Event for task handling */
+#define EVENT_TRANSVR_TASK_WAIT (2101)
+#define EVENT_TRANSVR_TASK_DONE (0)
+#define EVENT_TRANSVR_TASK_FAIL (-2101)
+/* Event for initial handling */
+#define EVENT_TRANSVR_INIT_UP (2201)
+#define EVENT_TRANSVR_INIT_DOWN (1)
+#define EVENT_TRANSVR_INIT_REINIT (-2201)
+#define EVENT_TRANSVR_INIT_FAIL (-2202)
+/* Event for others */
+#define EVENT_TRANSVR_RELOAD_FAIL (-2301)
+#define EVENT_TRANSVR_EXCEP_INIT (-2401)
+#define EVENT_TRANSVR_EXCEP_UP (-2402)
+#define EVENT_TRANSVR_EXCEP_DOWN (-2403)
+#define EVENT_TRANSVR_EXCEP_SWAP (-2404)
+#define EVENT_TRANSVR_EXCEP_EXCEP (-2405)
+#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406)
+#define EVENT_TRANSVR_I2C_CRASH (-2501)
+
+/* Transceiver error code define */
+#define ERR_TRANSVR_UNINIT (-201)
+#define ERR_TRANSVR_UNPLUGGED (-202)
+#define ERR_TRANSVR_ABNORMAL (-203)
+#define ERR_TRANSVR_NOSTATE (-204)
+#define ERR_TRANSVR_NOTSUPPORT (-205)
+#define ERR_TRANSVR_BADINPUT (-206)
+#define ERR_TRANSVR_UPDATE_FAIL (-207)
+#define ERR_TRANSVR_RELOAD_FAIL (-208)
+#define ERR_TRANSVR_INIT_FAIL (-209)
+#define ERR_TRANSVR_UNDEFINED (-210)
+#define ERR_TRANSVR_TASK_FAIL (-211)
+#define ERR_TRANSVR_TASK_BUSY (-212)
+#define ERR_TRANSVR_FUNC_DISABLE (-214)
+#define ERR_TRANSVR_I2C_CRASH (-297)
+#define ERR_TRNASVR_BE_ISOLATED (-298)
+#define ERR_TRANSVR_UNEXCPT (-299)
+
+/* For debug */
+#define DEBUG_TRANSVR_INT_VAL (-99)
+#define DEBUG_TRANSVR_HEX_VAL (0xfe)
+#define DEBUG_TRANSVR_STR_VAL "ERROR"
+
+/* For system internal */
+#define VAL_TRANSVR_COMID_ARREESS (0x50)
+#define VAL_TRANSVR_COMID_OFFSET (0x00)
+#define VAL_TRANSVR_8472_READY_ADDR (0x51)
+#define VAL_TRANSVR_8472_READY_PAGE (-1)
+#define VAL_TRANSVR_8472_READY_OFFSET (110)
+#define VAL_TRANSVR_8472_READY_BIT (0)
+#define VAL_TRANSVR_8472_READY_VALUE (0)
+#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff)
+#define VAL_TRANSVR_8436_READY_ADDR (0x50)
+#define VAL_TRANSVR_8436_READY_PAGE (-1)
+#define VAL_TRANSVR_8436_READY_OFFSET (2)
+#define VAL_TRANSVR_8436_READY_BIT (0)
+#define VAL_TRANSVR_8436_READY_VALUE (0)
+#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff)
+#define VAL_TRANSVR_8436_PWD_ADDR (0x50)
+#define VAL_TRANSVR_8436_PWD_PAGE (-1)
+#define VAL_TRANSVR_8436_PWD_OFFSET (123)
+#define VAL_TRANSVR_PAGE_FREE (-99)
+#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127)
+#define VAL_TRANSVR_PAGE_SELECT_DELAY (5)
+#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999)
+#define VAL_TRANSVR_FUNCTION_DISABLE (-1)
+#define STR_TRANSVR_QSFP "QSFP"
+#define STR_TRANSVR_QSFP_PLUS "QSFP+"
+#define STR_TRANSVR_QSFP28 "QSFP28"
+
+/* BCM chip type define */
+#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress */
+
+/* Info from transceiver EEPROM */
+struct eeprom_map_s {
+ int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los;
+ int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable;
+ int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault;
+};
+
+/* Class of transceiver object */
+struct transvr_obj_s {
+ /* ========== Object private property ==========
+ */
+ struct device *transvr_dev_p;
+ struct eeprom_map_s *eeprom_map_p;
+ struct i2c_client *i2c_client_p;
+ struct ioexp_obj_s *ioexp_obj_p;
+ struct mutex lock;
+ char swp_name[32];
+ int auto_tx_disable;
+ int chan_id;
+ int chipset_type;
+ int curr_page;
+ int info;
+ int ioexp_virt_offset;
+ int lane_id[8];
+ int layout;
+ int mode;
+ int retry;
+ int state;
+ int temp;
+ int type;
+
+ /* ========== Object private functions ==========
+ */
+ int (*init)(struct transvr_obj_s *self);
+ int (*update_all)(struct transvr_obj_s *self, int show_err);
+ int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name);
+};
+
+
+/* For AVL Mapping */
+struct transvr_avl_s {
+ char vendor_name[32];
+ char vendor_pn[32];
+ int (*init)(struct transvr_obj_s *self);
+};
+
+struct transvr_obj_s *
+create_transvr_obj(char *swp_name,
+ int chan_id,
+ struct ioexp_obj_s *ioexp_obj_p,
+ int ioexp_virt_offset,
+ int transvr_type,
+ int chipset_type,
+ int run_mode);
+
+void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg);
+
+#endif /* TRANSCEIVER_H */
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py
new file mode 100755
index 000000000000..f6f5e46c5536
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 Inventec, 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
+"""
+
+import os
+import commands
+import sys, getopt
+import logging
+import re
+import time
+from collections import namedtuple
+
+DEBUG = False
+args = []
+FORCE = 0
+i2c_prefix = '/sys/bus/i2c/devices/'
+
+
+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':
+ install()
+ elif arg == 'clean':
+ uninstall()
+ else:
+ show_help()
+
+
+ return 0
+
+def show_help():
+ print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
+ sys.exit(0)
+
+def show_log(txt):
+ if DEBUG == True:
+ print "[D7032]"+txt
+ return
+
+def exec_cmd(cmd, show):
+ logging.info('Run :'+cmd)
+ status, output = commands.getstatusoutput(cmd)
+ show_log (cmd +"with result:" + str(status))
+ show_log (" output:"+output)
+ if status:
+ logging.info('Failed :'+cmd)
+ if show:
+ print('Failed :'+cmd)
+ return status, output
+
+instantiate =[
+#'echo pca9545 0x70> /sys/bus/i2c/devices/i2c-0/new_device',
+#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-1/new_device',
+#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-2/new_device',
+#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-3/new_device',
+#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-4/new_device',
+#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-5/new_device',
+#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-5/new_device',
+'echo inv_eeprom 0x53> /sys/bus/i2c/devices/i2c-0/new_device']
+
+drivers =[
+'lpc_ich',
+'i2c-i801',
+'i2c-mux',
+'i2c-mux-pca954x',
+'i2c-dev',
+'inv_eeprom',
+'inv_platform',
+'inv_psoc',
+'inv_cpld',
+'swps']
+
+
+
+def system_install():
+ global FORCE
+
+ #remove default drivers to avoid modprobe order conflicts
+ status, output = exec_cmd("rmmod i2c_ismt ", 1)
+ status, output = exec_cmd("rmmod i2c-i801 ", 1)
+ #install drivers
+ for i in range(0,len(drivers)):
+ status, output = exec_cmd("modprobe "+drivers[i], 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+
+ #instantiate devices
+ for i in range(0,len(instantiate)):
+ time.sleep(1)
+ status, output = exec_cmd(instantiate[i], 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+
+ for i in range(22,30):
+ status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ for i in range(30,38):
+ status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ for i in range(6,14):
+ status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-2/i2c-"+str(i)+"/new_device", 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ for i in range(14,22):
+ status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-3/i2c-"+str(i)+"/new_device", 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ return
+
+
+def system_ready():
+ if not device_found():
+ return False
+ return True
+
+def install():
+ if not device_found():
+ print "No device, installing...."
+ status = system_install()
+ if status:
+ if FORCE == 0:
+ return status
+ else:
+ print " D7032 devices detected...."
+ return
+
+def uninstall():
+ global FORCE
+ #uninstall drivers
+ for i in range(len(drivers)-1,-1,-1):
+ status, output = exec_cmd("rmmod "+drivers[i], 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ return
+
+def device_found():
+ ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0)
+ ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0)
+ return not(ret1 or ret2)
+
+if __name__ == "__main__":
+ main()
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/onie-syseeprom b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/onie-syseeprom
deleted file mode 100755
index b8e3ba26a5d2..000000000000
Binary files a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/onie-syseeprom and /dev/null differ
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile
new file mode 100755
index 000000000000..aeffa4376588
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile
@@ -0,0 +1,6 @@
+obj-m += inv_cpld.o inv_psoc.o
+obj-m += inv_platform.o
+obj-m += inv_eeprom.o
+obj-m += swps.o
+swps-objs := inv_swps.o io_expander.o transceiver.o
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c
new file mode 100644
index 000000000000..683ffa0ff3ce
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "I2CHostCommunication.h"
+
+#define USE_SMBUS 1
+
+/* definition */
+#define CPLD_INFO_OFFSET 0x00
+#define CPLD_PSU_OFFSET 0x08
+#define CPLD_LED_OFFSET 0x0E
+#define CPLD_LED_STATU_OFFSET 0x0D
+#define CPLD_CTL_OFFSET 0x0C
+
+
+
+/* Each client has this additional data */
+struct cpld_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+/*-----------------------------------------------------------------------*/
+
+static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg[0].buf = msgbuf;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
+
+ status = i2c_transfer(client->adapter, msg, 2);
+
+ if(status == 2)
+ status = count;
+
+ return status;
+#endif
+}
+
+static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg.flags = 0;
+
+ /* msg.buf is u8 and casts will mask the values */
+ msg.buf = writebuf;
+
+ msg.buf[i++] = offset;
+ memcpy(&msg.buf[i], buf, count);
+ msg.len = i + count;
+
+ status = i2c_transfer(client->adapter, &msg, 1);
+ if (status == 1)
+ status = count;
+
+ return status;
+#endif
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t show_info(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 b[4];
+
+ memset(b, 0, 4);
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 4) return sprintf(buf, "read cpld info fail\n");
+
+ status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/
+ status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf);
+ status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf);
+
+ return strlen(buf);
+}
+
+
+static ssize_t show_ctl(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 b[1];
+
+ mutex_lock(&data->update_lock);
+
+ status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1);
+
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld ctl fail\n");
+
+
+ status = sprintf (buf, "0x%X\n", b[0]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_ctl(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+
+ u8 temp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1);
+ if(temp) byte |= (1<<0);
+ else byte &= ~(1<<0);
+ cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+
+static char* led_str[] = {
+ "OFF", //000
+ "0.5 Hz", //001
+ "1 Hz", //010
+ "2 Hz", //011
+ "NA", //100
+ "NA", //101
+ "NA", //110
+ "ON", //111
+};
+
+static ssize_t show_led(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET);
+
+ byte = (byte >> shift) & 0x7;
+
+ /*
+ 0: off
+ 1: 0.5hz
+ 2: 1 hz
+ 3: 2 hz
+ 4~6: not define
+ 7: on
+ */
+
+ status = sprintf (buf, "%d: %s\n", byte, led_str[byte]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_led(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ u8 temp = simple_strtol(buf, NULL, 16);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ temp &= 0x7;
+ //validate temp value: 0,1,2,3,7, TBD
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ byte &= ~(0x7<update_lock);
+
+ return count;
+}
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu0 | psu1
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 1)?0:3;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+
+static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0);
+static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0);
+
+static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0);
+static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1);
+
+static struct attribute *cpld_attributes[] = {
+ //info
+ &sensor_dev_attr_info.dev_attr.attr,
+ &sensor_dev_attr_ctl.dev_attr.attr,
+
+ &sensor_dev_attr_grn_led.dev_attr.attr,
+ &sensor_dev_attr_red_led.dev_attr.attr,
+
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.dev_attr.attr,
+
+ NULL
+};
+
+static const struct attribute_group cpld_group = {
+ .attrs = cpld_attributes,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* device probe and removal */
+
+static int
+cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct cpld_data *data;
+ int status;
+
+ printk("+%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &cpld_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: sensor '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &cpld_group);
+exit_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return status;
+}
+
+static int cpld_remove(struct i2c_client *client)
+{
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &cpld_group);
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id cpld_ids[] = {
+ { "inv_cpld", 0, },
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, cpld_ids);
+
+static struct i2c_driver cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "inv_cpld",
+ },
+ .probe = cpld_probe,
+ .remove = cpld_remove,
+ .id_table = cpld_ids,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* module glue */
+
+static int __init inv_cpld_init(void)
+{
+ return i2c_add_driver(&cpld_driver);
+}
+
+static void __exit inv_cpld_exit(void)
+{
+ i2c_del_driver(&cpld_driver);
+}
+
+MODULE_AUTHOR("eddie.lan ");
+MODULE_DESCRIPTION("inv cpld driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_cpld_init);
+module_exit(inv_cpld_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c
new file mode 100644
index 000000000000..3d13f3b04719
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE 256
+
+#define SLICE_BITS (6)
+#define SLICE_SIZE (1 << SLICE_BITS)
+#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE)
+
+/* Each client has this additional data */
+struct eeprom_data {
+ struct mutex update_lock;
+ u8 valid; /* bitfield, bit!=0 if slice is valid */
+ unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */
+ u8 data[EEPROM_SIZE]; /* Register values */
+};
+
+
+static void inv_eeprom_update_client(struct i2c_client *client, u8 slice)
+{
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ int i, j;
+ int ret;
+ int addr;
+
+
+ mutex_lock(&data->update_lock);
+
+ if (!(data->valid & (1 << slice)) ||
+ time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
+ dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
+
+ addr = slice << SLICE_BITS;
+
+ ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF);
+ /* select the eeprom address */
+ if (ret < 0) {
+ dev_err(&client->dev, "address set failed\n");
+ goto exit;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
+ goto exit;
+ }
+
+ for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
+ for (j = i; j < (i+SLICE_SIZE); j++) {
+ int res;
+
+ res = i2c_smbus_read_byte(client);
+ if (res < 0) {
+ goto exit;
+ }
+
+ data->data[j] = res & 0xFF;
+ }
+ }
+
+ data->last_updated[slice] = jiffies;
+ data->valid |= (1 << slice);
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+}
+
+static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ u8 slice;
+
+
+ if (off > EEPROM_SIZE) {
+ return 0;
+ }
+ if (off + count > EEPROM_SIZE) {
+ count = EEPROM_SIZE - off;
+ }
+ if (count == 0) {
+ return 0;
+ }
+
+ /* Only refresh slices which contain requested bytes */
+ for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
+ inv_eeprom_update_client(client, slice);
+ }
+
+ memcpy(buf, &data->data[off], count);
+
+ return count;
+}
+
+static struct bin_attribute inv_eeprom_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = inv_eeprom_read,
+};
+
+static int inv_eeprom_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct eeprom_data *data;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memset(data->data, 0xff, EEPROM_SIZE);
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* create the sysfs eeprom file */
+ err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ if (err) {
+ goto exit_kfree;
+ }
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int inv_eeprom_remove(struct i2c_client *client)
+{
+ sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static const struct i2c_device_id inv_eeprom_id[] = {
+ { "inv_eeprom", 0 },
+ { }
+};
+
+static struct i2c_driver inv_eeprom_driver = {
+ .driver = {
+ .name = "inv_eeprom",
+ },
+ .probe = inv_eeprom_probe,
+ .remove = inv_eeprom_remove,
+ .id_table = inv_eeprom_id,
+};
+
+module_i2c_driver(inv_eeprom_driver);
+
+MODULE_AUTHOR("Inventec");
+MODULE_DESCRIPTION("Inventec D7054 Mother Board EEPROM driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c
new file mode 100644
index 000000000000..ea26970075b0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c
@@ -0,0 +1,219 @@
+#include
+//#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+//#include
+//#include
+
+//#include
+//#define IO_EXPAND_BASE 64
+//#define IO_EXPAND_NGPIO 16
+
+struct inv_i2c_board_info {
+ int ch;
+ int size;
+ struct i2c_board_info *board_info;
+};
+
+#define bus_id(id) (id)
+static struct pca954x_platform_mode mux_modes_0[] = {
+ {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
+ {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
+ {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
+ {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
+};
+static struct pca954x_platform_mode mux_modes_0_0[] = {
+ {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
+ {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
+ {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
+ {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_1[] = {
+ {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
+ {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
+ {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
+ {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_2[] = {
+ {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
+ {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
+ {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
+ {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_3[] = {
+ {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
+ {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
+ {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),},
+ {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_4[] = {
+ {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),},
+ {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),},
+ {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),},
+ {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_5[] = {
+ {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),},
+ {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),},
+ {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),},
+ {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_6[] = {
+ {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),},
+ {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),},
+ {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),},
+ {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),},
+};
+
+//no i2c device driver attach to mux 7
+
+
+static struct pca954x_platform_data mux_data_0 = {
+ .modes = mux_modes_0,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_0 = {
+ .modes = mux_modes_0_0,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_1 = {
+ .modes = mux_modes_0_1,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_2 = {
+ .modes = mux_modes_0_2,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_3 = {
+ .modes = mux_modes_0_3,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_4 = {
+ .modes = mux_modes_0_4,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_5 = {
+ .modes = mux_modes_0_5,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_6 = {
+ .modes = mux_modes_0_6,
+ .num_modes = 8,
+};
+
+static struct i2c_board_info i2c_device_info0[] __initdata = {
+ {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
+ {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
+ {"pca9548", 0, 0x71, &mux_data_0, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info2[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
+};
+static struct i2c_board_info i2c_device_info3[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
+};
+static struct i2c_board_info i2c_device_info4[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
+};
+static struct i2c_board_info i2c_device_info5[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
+};
+static struct i2c_board_info i2c_device_info6[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0},
+};
+static struct i2c_board_info i2c_device_info7[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0},
+};
+static struct i2c_board_info i2c_device_info8[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0},
+};
+
+
+static struct inv_i2c_board_info i2cdev_list[] = {
+ {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0
+
+ {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
+ {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
+ {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
+ {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
+ {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4
+ {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5
+ {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6
+
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+#if 0
+static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
+ .scl_pin = 58,
+ .sda_pin = 75,
+
+ .udelay = 5, //5:100kHz
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0
+};
+
+static struct platform_device device_i2c_gpio0 = {
+ .name = "i2c-gpio",
+ .id = 0, // adapter number
+ .dev.platform_data = &i2c_gpio_platdata0,
+};
+#endif
+static int __init inv_platform_init(void)
+{
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *e = NULL;
+ int ret = 0;
+ int i,j;
+
+ printk("%s \n", __func__);
+
+#if 0
+ //use i2c-gpio
+ //register i2c gpio
+ //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3
+ outl( inl(0x533) | (1<<2), 0x533);
+ outl( inl(0x541) | (1<<3), 0x541);
+
+ ret = platform_device_register(&device_i2c_gpio0);
+ if (ret) {
+ printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret);
+ }
+ #endif
+ for(i=0; i
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "I2CHostCommunication.h"
+
+#define IMPLEMENT_IPMI_CODE 1
+int USE_IPMI=0;
+//=================================
+#if IMPLEMENT_IPMI_CODE
+#include
+#include
+#include
+#include
+
+#define IPMI_MAX_INTF (4)
+#define NETFN_OEM 0x30
+#define CMD_GETDATA 0x31
+#define CMD_SETDATA 0x32
+
+struct mutex ipmi_mutex;
+
+static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data);
+static ipmi_user_t ipmi_mh_user = NULL;
+static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
+
+static atomic_t dummy_count = ATOMIC_INIT(0);
+static void dummy_smi_free(struct ipmi_smi_msg *msg)
+{
+ atomic_dec(&dummy_count);
+}
+static void dummy_recv_free(struct ipmi_recv_msg *msg)
+{
+ atomic_dec(&dummy_count);
+}
+static struct ipmi_smi_msg halt_smi_msg = {
+ .done = dummy_smi_free
+};
+static struct ipmi_recv_msg halt_recv_msg = {
+ .done = dummy_recv_free
+};
+#endif
+//=================================
+
+#define USE_SMBUS 1
+
+#define FAN_NUM 4
+#define PSU_NUM 2
+
+struct __attribute__ ((__packed__)) psoc_psu_layout {
+ u16 psu1_iin;
+ u16 psu2_iin;
+ u16 psu1_iout;
+ u16 psu2_iout;
+
+ u16 psu1_pin;
+ u16 psu2_pin;
+ u16 psu1_pout;
+ u16 psu2_pout;
+
+ u16 psu1_vin;
+ u16 psu2_vin;
+ u16 psu1_vout;
+ u16 psu2_vout;
+};
+
+struct __attribute__ ((__packed__)) psoc_layout {
+ u8 ctl; //offset: 0
+ u16 switch_temp; //offset: 1
+ u8 reserve0; //offset: 3
+
+ u8 fw_upgrade; //offset: 4
+
+ //i2c bridge
+ u8 i2c_st; //offset: 5
+ u8 i2c_ctl; //offset: 6
+ u8 i2c_addr; //offset: 7
+ u8 i2c_data[0x20]; //offset: 8
+
+ //gpo
+ u8 led_ctl; //offset: 28
+
+ u8 gpio; //offset: 29
+
+ //pwm duty
+ u8 pwm[FAN_NUM]; //offset: 2a
+ u8 pwm_psu[PSU_NUM]; //offset: 2e
+
+ //fan rpm
+ u16 fan[FAN_NUM*2]; //offset: 30
+
+ u8 reserve1[4]; //offset: 40
+
+ //gpi
+ u8 gpi_fan; //offset: 44
+
+ //psu state
+ u8 psu_state; //offset: 45
+
+ //temperature
+ u16 temp[5]; //offset: 46
+ u16 temp_psu[PSU_NUM]; //offset: 50
+
+ //version
+ u8 version[2]; //offset: 54
+
+ u8 reserve2[4]; //offset: 56
+ struct psoc_psu_layout psu_info; //offset: 5a
+};
+
+/* definition */
+/* definition */
+#define PSOC_OFF(m) offsetof(struct psoc_layout, m)
+#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m)
+
+#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp)
+#define PWM_OFFSET PSOC_OFF(pwm)
+#define THERMAL_OFFSET PSOC_OFF(temp)
+#define RPM_OFFSET PSOC_OFF(fan)
+#define DIAG_FLAG_OFFSET PSOC_OFF(ctl)
+#define FAN_LED_OFFSET PSOC_OFF(led_ctl)
+#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan)
+#define PSOC_PSU_OFFSET PSOC_OFF(psu_state)
+#define VERSION_OFFSET PSOC_OFF(version)
+#define PSU_INFO_OFFSET PSOC_OFF(psu_info)
+
+/* Each client has this additional data */
+struct psoc_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ u32 diag;
+};
+
+/*-----------------------------------------------------------------------*/
+#if IMPLEMENT_IPMI_CODE
+static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
+{
+ struct completion *comp = recv_msg->user_msg_data;
+ if (comp)
+ complete(comp);
+ else
+ ipmi_free_recv_msg(recv_msg);
+ return;
+}
+
+int ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length)
+{
+ int rv=0,i;
+ struct ipmi_system_interface_addr addr;
+ uint8_t _data[data_length];
+ struct kernel_ipmi_msg msg;
+ struct completion comp;
+
+ if(!mutex_trylock(&ipmi_mutex)) return 0;
+
+// for (i=0,rv=1; iaddr;
+ msg[0].buf = msgbuf;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
+
+ status = i2c_transfer(client->adapter, msg, 2);
+
+ if(status == 2)
+ status = count;
+
+ return status;
+#endif
+}
+
+static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{
+#if USE_SMBUS
+if(USE_IPMI==0)
+{
+ int i;
+
+ for(i=0; iaddr;
+ msg.flags = 0;
+
+ /* msg.buf is u8 and casts will mask the values */
+ msg.buf = writebuf;
+
+ msg.buf[i++] = offset;
+ memcpy(&msg.buf[i], buf, count);
+ msg.len = i + count;
+
+ status = i2c_transfer(client->adapter, &msg, 1);
+ if (status == 1)
+ status = count;
+
+ return status;
+#endif
+}
+
+#if 0
+static u32 psoc_read32(struct i2c_client *client, u8 offset)
+{
+ u32 value = 0;
+ u8 buf[4];
+
+ if( psoc_i2c_read(client, buf, offset, 4) == 4)
+ value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]);
+
+ return value;
+}
+#endif
+
+static u16 psoc_read16(struct i2c_client *client, u8 offset)
+{
+ u16 value = 0;
+ u8 buf[2];
+
+ if(psoc_i2c_read(client, buf, offset, 2) == 2)
+ value = (buf[0]<<8 | buf[1]<<0);
+
+ return value;
+}
+
+static u8 psoc_read8(struct i2c_client *client, u8 offset)
+{
+ u8 value = 0;
+ u8 buf = 0;
+
+ if(psoc_i2c_read(client, &buf, offset, 1) == 1)
+ value = buf;
+
+ return value;
+}
+
+//PSOC i2c bridge regsters
+#define PSOC_I2C_STATUS 0x05
+#define PSOC_I2C_CNTRL 0x06
+#define PSOC_I2C_ADDR 0x07
+#define PSOC_I2C_DATA 0x08
+
+//status bit definition
+#define PSOC_I2C_START (1 << 0)
+#define PSOC_PMB_SEL (1 << 7)
+
+//addr bits definition
+#define PSOC_I2C_READ (1 << 0)
+
+//PMBUS registers definition
+#define PMBUS_READ_VIN (0x88)
+#define PMBUS_READ_IIN (0x89)
+#define PMBUS_READ_VOUT (0x8B)
+#define PMBUS_READ_IOUT (0x8C)
+#define PMBUS_READ_POUT (0x96)
+#define PMBUS_READ_PIN (0x97)
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu1 | psu0
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu_st(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+#define PSU1 0x5800
+#define PSU2 0x5900
+#define BMC_I2cBus 3 //BMC's I2C-1
+#define PMBus_Vender 0x99
+#define PMBus_Serial 0x9E
+#define PMBus_Temp2 0x8E
+#define PMBus_Version 0x9B
+#define MaxLeng_Result 0x20
+#define MaxLog
+static long pmbus_reg2data_linear(int data, int linear16);
+
+
+static ssize_t show_ipmi_i2c(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ uint8_t data[4],result[MaxLeng_Result];
+ int result_len;
+
+ data[0] = BMC_I2cBus;
+ data[1] = (attr->index & 0xFF00 ) >>7;
+ data[3] = attr->index & 0xff;
+ if(data[3]==PMBus_Temp2)
+ data[2]=2;
+ else
+ data[2]=MaxLeng_Result;
+
+ if(ipmi_command(0x06, 0x52,data,4, result, &result_len)==0)
+ {
+ if(data[3]==PMBus_Temp2)
+ {
+ return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 ));
+ }
+ result[result[0]+1]='\0';
+
+ return sprintf(buf, "%s\n",&result[1] );
+ }
+ else
+ return 0;
+}
+
+static ssize_t show_ipmi_sollog(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ uint8_t data[5],result[256];
+ int result_len;
+ uint32_t i;
+
+ for(i=0;i<0xffffff;i+=255)
+ {
+ data[0] = attr->index;
+ data[1] = (i & 0x0000ff);
+ data[2] = (i & 0x00ff00)>>8;
+ data[3] = (i & 0xff0000)>>16;
+ data[4] = 0;
+
+ result_len=0;
+
+ if(ipmi_command(0x32, 0xFE, data, 5, result, &result_len)==0)
+ {
+ if(result_len==0) break;
+ result[result_len+1]='\0';
+ printk("%s",result);
+ }
+ else break;
+
+ if(result_len==0) break;
+ }
+
+ return 0;
+}
+
+static ssize_t show_thermal(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index * 2 + THERMAL_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ (s8)(status>>8) * 1000 );
+}
+
+
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t set_pwm(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ u8 pwm = simple_strtol(buf, NULL, 10);
+ if(pwm > 255) pwm = 255;
+
+ if(data->diag) {
+ mutex_lock(&data->update_lock);
+ psoc_i2c_write(client, &pwm, offset, 1);
+ mutex_unlock(&data->update_lock);
+ }
+
+ return count;
+}
+
+
+static ssize_t show_rpm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index*2 + RPM_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u16 temp = 0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2);
+ mutex_unlock(&data->update_lock);
+
+ status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 );
+
+ return strlen(buf);
+}
+
+static ssize_t set_switch_tmp(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ long temp = simple_strtol(buf, NULL, 10);
+ u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ;
+
+ //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF));
+
+ mutex_lock(&data->update_lock);
+ psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_diag(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 diag_flag = 0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ data->diag = (diag_flag & 0x80)?1:0;
+ status = sprintf (buf, "%d\n", data->diag);
+
+ return strlen(buf);
+}
+
+static ssize_t set_diag(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 value = 0;
+ u8 diag = simple_strtol(buf, NULL, 10);
+
+ diag = diag?1:0;
+ data->diag = diag;
+
+ mutex_lock(&data->update_lock);
+ psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1);
+ if(diag) value |= (1<<7);
+ else value &= ~(1<<7);
+ psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, VERSION_OFFSET);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) );
+}
+
+
+static ssize_t show_fan_led(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 bit = attr->index;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, FAN_LED_OFFSET);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ (status & (1<index;
+ u8 led_state = 0;
+
+ u8 v = simple_strtol(buf, NULL, 10);
+
+ if(data->diag) {
+ mutex_lock(&data->update_lock);
+ led_state = psoc_read8(client, FAN_LED_OFFSET);
+ if(v) led_state |= (1<update_lock);
+ }
+
+ return count;
+}
+
+static ssize_t show_value8(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "0x%02X\n", status );
+}
+
+static long pmbus_reg2data_linear(int data, int linear16)
+{
+ s16 exponent;
+ s32 mantissa;
+ long val;
+
+ if (linear16) { /* LINEAR16 */
+ exponent = -9;
+ mantissa = (u16) data;
+ } else { /* LINEAR11 */
+ exponent = ((s16)data) >> 11;
+ exponent = ((s16)( data & 0xF800) ) >> 11;
+ mantissa = ((s32)((data & 0x7ff) << 5)) >> 5;
+ }
+
+ //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa);
+ val = mantissa;
+
+ /* scale result to micro-units for power sensors */
+ val = val * 1000L;
+
+ if (exponent >= 0)
+ val <<= exponent;
+ else
+ val >>= -exponent;
+
+ return val;
+}
+
+static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index + PSU_INFO_OFFSET;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_read16(client, offset);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 ));
+}
+
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4);
+static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5);
+static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3);
+static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7);
+static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8);
+static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9);
+
+static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
+
+static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0);
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0);
+
+static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0);
+static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1);
+static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2);
+static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3);
+static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4);
+static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5);
+static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6);
+static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7);
+
+static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET);
+static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout));
+
+
+static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout));
+
+//IPMI
+static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Temp2);
+static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Vender);
+static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Serial);
+static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Version);
+
+static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Temp2);
+static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Vender);
+static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Serial);
+static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Version);
+
+static SENSOR_DEVICE_ATTR(sollog1, S_IRUGO, show_ipmi_sollog, 0, 1);
+static SENSOR_DEVICE_ATTR(sollog2, S_IRUGO, show_ipmi_sollog, 0, 2);
+
+static struct attribute *psoc_attributes[] = {
+ //thermal
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
+ &sensor_dev_attr_temp5_input.dev_attr.attr,
+
+ &sensor_dev_attr_thermal_psu1.dev_attr.attr,
+ &sensor_dev_attr_thermal_psu2.dev_attr.attr,
+
+
+ //pwm
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm4.dev_attr.attr,
+ &sensor_dev_attr_pwm_psu1.dev_attr.attr,
+ &sensor_dev_attr_pwm_psu2.dev_attr.attr,
+
+ //rpm
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+
+ &sensor_dev_attr_rpm_psu1.dev_attr.attr,
+ &sensor_dev_attr_rpm_psu2.dev_attr.attr,
+
+ //switch temperature
+ &sensor_dev_attr_switch_tmp.dev_attr.attr,
+
+ //diag flag
+ &sensor_dev_attr_diag.dev_attr.attr,
+
+ //version
+ &sensor_dev_attr_version.dev_attr.attr,
+
+ //fan led
+ &sensor_dev_attr_fan_led_grn1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn4.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red4.dev_attr.attr,
+
+ //fan GPI
+ &sensor_dev_attr_fan_gpi.dev_attr.attr,
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.dev_attr.attr,
+
+
+ //psu_psoc, new added on psoc 1.9
+ &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr,
+
+ //ipmi_command
+ &sensor_dev_attr_thermal2_psu1.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_vender.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_version.dev_attr.attr,
+
+ &sensor_dev_attr_thermal2_psu2.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vender.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_version.dev_attr.attr,
+
+ &sensor_dev_attr_sollog1.dev_attr.attr,
+ &sensor_dev_attr_sollog2.dev_attr.attr,
+
+ NULL
+};
+
+static const struct attribute_group psoc_group = {
+ .attrs = psoc_attributes,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* device probe and removal */
+
+static int
+psoc_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct psoc_data *data;
+ int status,i,rv;
+
+ printk("+%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->diag = 0;
+
+#if IMPLEMENT_IPMI_CODE
+ for (i=0,rv=1; idev.kobj, &psoc_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: sensor '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &psoc_group);
+exit_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return status;
+}
+
+static int psoc_remove(struct i2c_client *client)
+{
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &psoc_group);
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id psoc_ids[] = {
+ { "inv_psoc", 0, },
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, psoc_ids);
+
+static struct i2c_driver psoc_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "inv_psoc",
+ },
+ .probe = psoc_probe,
+ .remove = psoc_remove,
+ .id_table = psoc_ids,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* module glue */
+
+static int __init inv_psoc_init(void)
+{
+ return i2c_add_driver(&psoc_driver);
+}
+
+static void __exit inv_psoc_exit(void)
+{
+ i2c_del_driver(&psoc_driver);
+}
+
+MODULE_AUTHOR("eddie.lan ");
+MODULE_DESCRIPTION("inv psoc driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_psoc_init);
+module_exit(inv_psoc_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c
new file mode 100644
index 000000000000..08bd490e63b6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c
@@ -0,0 +1,730 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "inv_swps.h"
+
+static int port_major;
+static int ioexp_total;
+static int port_total;
+static struct class *swp_class_p = NULL;
+static struct inv_platform_s *platform_p = NULL;
+static struct inv_ioexp_layout_s *ioexp_layout = NULL;
+static struct inv_port_layout_s *port_layout = NULL;
+
+static int
+__swp_match(struct device *dev,
+#ifdef SWPS_KERN_VER_AF_3_10
+
+ const void *data){
+#else
+ void *data){
+#endif
+
+ char *name = (char *)data;
+ if (strcmp(dev_name(dev), name) == 0)
+ return 1;
+ return 0;
+}
+
+
+struct device *
+get_swpdev_by_name(char *name){
+ struct device *dev = class_find_device(swp_class_p,
+ NULL,
+ name,
+ (const void *)__swp_match);
+ return dev;
+}
+
+
+static int
+sscanf_2_int(const char *buf) {
+
+ int result = -EBFONT;
+ char *hex_tag = "0x";
+
+ if (strcspn(buf, hex_tag) == 0) {
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ } else {
+ if (sscanf(buf,"%d",&result)) {
+ return result;
+ }
+ if(sscanf(buf,"-%d",&result)) {
+ return -result;
+ }
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ }
+ return -EBFONT;
+}
+
+
+static int
+sscanf_2_binary(const char *buf) {
+
+ int result = sscanf_2_int(buf);
+
+ if (result < 0){
+ return -EBFONT;
+ }
+ switch (result) {
+ case 0:
+ case 1:
+ return result;
+ default:
+ break;
+ }
+ return -EBFONT;
+}
+
+/* ========== Show functions: For I/O Expander attribute ==========
+ */
+static ssize_t
+_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset),
+ char *buf_p) {
+ size_t len;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ mutex_lock(&ioexp_p->lock);
+ len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset));
+ mutex_unlock(&ioexp_p->lock);
+ return len;
+}
+
+
+static ssize_t
+show_attr_present(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_present,
+ buf_p);
+}
+
+static ssize_t
+show_attr_tx_fault(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_tx_fault,
+ buf_p);
+}
+
+static ssize_t
+show_attr_rxlos(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_rxlos,
+ buf_p);
+}
+
+static ssize_t
+show_attr_tx_disable(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_tx_disable,
+ buf_p);
+}
+
+static ssize_t
+show_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_reset,
+ buf_p);
+}
+
+static ssize_t
+show_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_lpmod,
+ buf_p);
+}
+
+
+static ssize_t
+show_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_modsel,
+ buf_p);
+}
+
+/* ========== Store functions: For I/O Expander (R/W) attribute ==========
+ */
+static ssize_t
+_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*set_func)(struct ioexp_obj_s *ioexp_p,
+ int virt_offset, int input_val),
+ const char *buf_p,
+ size_t count) {
+
+ int input, err;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR("%s: data corruption! :%s\n",
+ __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ input = sscanf_2_binary(buf_p);
+ if (input < 0) {
+ return -EBFONT;
+ }
+ mutex_lock(&ioexp_p->lock);
+ err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input);
+ mutex_unlock(&ioexp_p->lock);
+ if (err < 0){
+ return err;
+ }
+ return count;
+}
+
+static ssize_t
+store_attr_tx_disable(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_tx_disable,
+ buf_p,
+ count);
+}
+
+static ssize_t
+store_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_reset,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_lpmod,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_modsel,
+ buf_p,
+ count);
+}
+
+/* ========== IO Expander attribute: from expander ==========
+ */
+static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL);
+static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL);
+static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL);
+static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable);
+static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset);
+static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod);
+static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel);
+
+/* ========== Functions for module handling ==========
+ */
+static void
+clean_port_obj(void){
+
+ dev_t dev_num;
+ char dev_name[32];
+ struct device *device_p;
+ struct transvr_obj_s *transvr_obj_p;
+ int minor_curr, port_id;
+
+ for (minor_curr=0; minor_curri2c_client_p);
+ kfree(transvr_obj_p);
+ }
+ dev_num = MKDEV(port_major, minor_curr);
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+static int
+get_platform_type(void){
+
+ char log_msg[64] = "ERROR";
+
+ platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL);
+ if (!platform_p){
+ snprintf(log_msg, sizeof(log_msg), "kzalloc fail");
+ goto err_get_platform_type_1;
+ }
+ platform_p->id = PLATFORM_SETTINGS;
+ memset(platform_p->name, 0, sizeof(platform_p->name));
+ snprintf(platform_p->name, (sizeof(platform_p->name) - 1),
+ "%s", platform_map.name);
+ snprintf(log_msg, sizeof(log_msg),
+ "User setup platform: %d (%s)",
+ platform_p->id, platform_p->name);
+ SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return 0;
+
+err_get_platform_type_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return -1;
+}
+
+
+static int
+get_layout_info(void){
+ ioexp_layout = cypress_ga2_ioexp_layout;
+ port_layout = cypress_ga2_port_layout;
+ ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout);
+ port_total = ARRAY_SIZE(cypress_ga2_port_layout);
+
+ SWPS_INFO("Start to initial platform: %d (%s)\n",
+ platform_p->id, platform_p->name);
+ return 0;
+}
+
+/* ========== Functions for register something ==========
+ */
+
+static int
+register_ioexp_attr_sfp_1(struct device *device_p){
+ /* Support machine type:
+ * - SFP : Magnolia
+ */
+ char *err_attr = NULL;
+
+ if (device_create_file(device_p, &dev_attr_present) < 0) {
+ err_attr = "dev_attr_present";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_tx_fault) < 0) {
+ err_attr = "dev_attr_tx_fault";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_rxlos) < 0) {
+ err_attr = "dev_attr_rxlos";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_tx_disable) < 0) {
+ err_attr = "dev_attr_tx_disable";
+ goto err_ioexp_sfp1_attr;
+ }
+ return 0;
+
+err_ioexp_sfp1_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr_sfp_2(struct device *device_p){
+ /* Support machine type:
+ * - SFP28 : Cypress
+ */
+ char *err_attr = NULL;
+
+ if (register_ioexp_attr_sfp_1(device_p) < 0){
+ goto err_ioexp_sfp2_attr;
+ }
+ return 0;
+
+err_ioexp_sfp2_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr_qsfp_1(struct device *device_p){
+ /* Support machine type:
+ * - QSFP : Magnolia, Redwood, Hudson32i
+ * - QSFP+ : Magnolia, Redwood, Hudson32i
+ * - QSFP28: Redwood
+ */
+ char *err_attr = NULL;
+
+ if (device_create_file(device_p, &dev_attr_present) < 0) {
+ err_attr = "dev_attr_present";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_reset) < 0) {
+ err_attr = "dev_attr_reset";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_lpmod) < 0) {
+ err_attr = "dev_attr_lpmod";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_modsel) < 0) {
+ err_attr = "dev_attr_modsel";
+ goto err_ioexp_qsfp1_attr;
+ }
+ return 0;
+
+err_ioexp_qsfp1_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr(struct device *device_p,
+ struct transvr_obj_s *transvr_obj){
+
+ char *err_msg = "ERR";
+
+ switch (transvr_obj->ioexp_obj_p->ioexp_type){
+ case IOEXP_TYPE_CYPRESS_NABC:
+ if (register_ioexp_attr_sfp_2(device_p) < 0){
+ err_msg = "register_ioexp_attr_sfp_2 fail";
+ goto err_reg_ioexp_attr;
+ }
+ break;
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ if (register_ioexp_attr_qsfp_1(device_p) < 0){
+ err_msg = "register_ioexp_attr_qsfp_1 fail";
+ goto err_reg_ioexp_attr;
+ }
+ break;
+
+ default:
+ err_msg = "Unknow type";
+ goto err_reg_ioexp_attr;
+ }
+ return 0;
+
+err_reg_ioexp_attr:
+ SWPS_ERR("%s: %s :%d \n",
+ __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type);
+ return -1;
+}
+
+
+static int
+register_port_device(char *dev_name,
+ dev_t dev_num,
+ struct transvr_obj_s *transvr_obj){
+
+ struct device *device_p = NULL;
+ device_p = device_create(swp_class_p, /* struct class *cls */
+ NULL, /* struct device *parent */
+ dev_num, /* dev_t devt */
+ transvr_obj, /* void *private_data */
+ dev_name); /* const char *fmt */
+ if (IS_ERR(device_p)){
+ goto err_regswp_create_dev;
+ }
+ if (register_ioexp_attr(device_p, transvr_obj) < 0){
+ goto err_regswp_reg_attr;
+ }
+ return 0;
+
+err_regswp_reg_attr:
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+err_regswp_create_dev:
+ SWPS_ERR("%s fail! :%s\n", __func__, dev_name);
+ return -1;
+}
+
+
+static int
+register_swp_module(void){
+
+ dev_t port_devt = 0;
+ int dev_total = port_total + 1; /* char_dev for module control */
+
+ if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){
+ SWPS_WARN("Allocate PORT MAJOR failure! \n");
+ goto err_register_swp_module_3;
+ }
+ port_major = MAJOR(port_devt);
+
+ /* Create class object */
+ swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME);
+ if (IS_ERR(swp_class_p)) {
+ SWPS_ERR("Create class failure! \n");
+ goto err_register_swp_module_3;
+ }
+ return 0;
+
+err_register_swp_module_3:
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ return -1;
+}
+
+
+/* ========== Module initial relate ==========
+ */
+static int
+create_ioexp_objs(void) {
+
+ int i, run_mod;
+
+ /* Clean IOEXP object */
+ clean_ioexp_objs();
+ /* Get running mode */
+ run_mod = IOEXP_MODE_DIRECT;
+ /* Create IOEXP object */
+ for(i=0; i devlen_max) {
+ snprintf(err_msg, sizeof(err_msg),
+ "SWP_DEV_PORT too long!");
+ goto err_initport_create_tranobj;
+ }
+ memset(dev_name, 0, sizeof(dev_name));
+ snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id);
+ /* Create transceiver object */
+ ioexp_obj_p = get_ioexp_obj(ioexp_id);
+ if (!ioexp_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "IOEXP object:%d not exist", ioexp_id);
+ goto err_initport_create_tranobj;
+ }
+ transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p,
+ ioexp_virt_offset, transvr_type,
+ chipset_type, run_mod);
+ if (!transvr_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "Create transceiver object fail :%s", dev_name);
+ goto err_initport_create_tranobj;
+ }
+ /* Setup Lane_ID mapping */
+ i = ARRAY_SIZE(port_layout[minor_curr].lane_id);
+ j = ARRAY_SIZE(transvr_obj_p->lane_id);
+ if (i != j) {
+ snprintf(err_msg, sizeof(err_msg),
+ "Lane_id size inconsistent %d/%d", i, j);
+ goto err_initport_reg_device;
+ }
+ memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int));
+ /* Create and register device object */
+ if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){
+ snprintf(err_msg, sizeof(err_msg),
+ "register_port_device fail");
+ goto err_initport_reg_device;
+ }
+ /* Setup device_ptr of transvr_obj */
+ dev_p = get_swpdev_by_name(dev_name);
+ if (!dev_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "get_swpdev_by_name fail");
+ goto err_initport_reg_device;
+ }
+ transvr_obj_p->transvr_dev_p = dev_p;
+ /* Success */
+ ok_count++;
+ }
+ SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count);
+ return 0;
+
+err_initport_reg_device:
+ kfree(transvr_obj_p);
+err_initport_create_tranobj:
+ clean_port_obj();
+ SWPS_ERR("%s: %s", __func__, err_msg);
+ SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n",
+ port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod);
+ return -1;
+}
+
+static int __init
+swp_module_init(void){
+
+ if (get_platform_type() < 0){
+ goto err_init_out;
+ }
+ if (get_layout_info() < 0){
+ goto err_init_out;
+ }
+ if (register_swp_module() < 0){
+ goto err_init_out;
+ }
+ if (create_ioexp_objs() < 0){
+ goto err_init_ioexp;
+ }
+ if (create_port_objs() < 0){
+ goto err_init_portobj;
+ }
+ if (init_ioexp_objs() < 0){
+ goto err_init_portobj;
+ }
+ SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION);
+ return 0;
+
+
+err_init_portobj:
+ clean_ioexp_objs();
+err_init_ioexp:
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+err_init_out:
+ SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION);
+ return -1;
+}
+
+
+static void __exit
+swp_module_exit(void){
+ clean_port_obj();
+ clean_ioexp_objs();
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ SWPS_INFO("Remove Inventec switch-port module success.\n");
+}
+
+
+/* Module information */
+MODULE_AUTHOR(SWP_AUTHOR);
+MODULE_DESCRIPTION(SWP_DESC);
+MODULE_VERSION(SWP_VERSION);
+MODULE_LICENSE(SWP_LICENSE);
+
+module_init(swp_module_init);
+module_exit(swp_module_exit);
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h
new file mode 100644
index 000000000000..f37fd387e4a5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h
@@ -0,0 +1,170 @@
+#ifndef INV_SWPS_H
+#define INV_SWPS_H
+
+#include "transceiver.h"
+#include "io_expander.h"
+
+/* Module settings */
+#define SWP_CLS_NAME "swps"
+#define SWP_DEV_PORT "port"
+#define SWP_AUTOCONFIG_ENABLE (1)
+
+/* Module information */
+#define SWP_AUTHOR "Neil "
+#define SWP_DESC "Inventec port and transceiver driver"
+#define SWP_VERSION "4.2.3"
+#define SWP_LICENSE "GPL"
+
+/* Module status define */
+#define SWP_STATE_NORMAL (0)
+#define SWP_STATE_I2C_DIE (-91)
+
+/* [Note]:
+ * Functions and mechanism for auto-detect platform type is ready,
+ * But HW and BIOS not ready! We need to wait them.
+ * So, please do not use PLATFORM_TYPE_AUTO until they are ready.
+ * (2016.06.13)
+ */
+#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */
+#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */
+
+/* Current running platfrom */
+#define PLATFORM_SETTINGS PLATFORM_TYPE_CYPRESS_GA2
+
+/* Define platform flag and kernel version */
+#if (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2)
+ #define SWPS_KERN_VER_BF_3_8 (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI)
+ #define SWPS_KERN_VER_AF_3_10 (1)
+#endif
+
+
+struct inv_platform_s {
+ int id;
+ char name[64];
+};
+
+struct inv_ioexp_layout_s {
+ int ioexp_id;
+ int ioexp_type;
+ struct ioexp_addr_s addr[4];
+};
+
+struct inv_port_layout_s {
+ int port_id;
+ int chan_id;
+ int ioexp_id;
+ int ioexp_offset;
+ int transvr_type;
+ int chipset_type;
+ int lane_id[8];
+};
+
+/* ==========================================
+ * Inventec Platform Settings
+ * ==========================================
+ */
+struct inv_platform_s platform_map = {PLATFORM_TYPE_CYPRESS_GA2, "D7054Q28B" };
+
+/* ==========================================
+ * Cypress Layout configuration (Inventec version [Down->Up])
+ * ==========================================
+ */
+struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = {
+ /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+ {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
+ {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
+ {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+ },
+ {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */
+ {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */
+ {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+ },
+};
+
+struct inv_port_layout_s cypress_ga2_port_layout[] = {
+ /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+ { 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} },
+ { 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} },
+ { 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} },
+ { 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} },
+ { 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} },
+ { 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} },
+ { 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} },
+ { 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} },
+ { 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} },
+ { 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} },
+ {10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} },
+ {11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} },
+ {12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} },
+ {13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} },
+ {14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} },
+ {15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} },
+ {16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} },
+ {17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} },
+ {18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} },
+ {19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} },
+ {20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} },
+ {21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} },
+ {22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} },
+ {23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} },
+ {24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} },
+ {25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} },
+ {26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} },
+ {27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} },
+ {28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} },
+ {29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} },
+ {30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} },
+ {31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} },
+ {32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} },
+ {33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} },
+ {34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} },
+ {35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} },
+ {36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} },
+ {37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} },
+ {38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} },
+ {39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} },
+ {40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} },
+ {41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} },
+ {42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} },
+ {43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} },
+ {44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} },
+ {45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} },
+ {46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} },
+ {47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} },
+ {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+ {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+ {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+ {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+ {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+ {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+};
+
+
+#endif /* SFP_DRIVER_H */
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c
new file mode 100644
index 000000000000..057995e4551a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c
@@ -0,0 +1,944 @@
+#include
+#include
+#include "io_expander.h"
+
+static struct ioexp_obj_s *ioexp_head_p = NULL;
+static struct ioexp_obj_s *ioexp_tail_p = NULL;
+
+struct ioexp_map_s ioexp_map_cypress_nabc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */
+ {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+ {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+ {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+ {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+ {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+ {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+ {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+ },
+ .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */
+ {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+ {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+ {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+ {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+ {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+ {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+ {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+ },
+ .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */
+ {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+ {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+ {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+ {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+ {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+ {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+ {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+ },
+};
+
+struct ioexp_map_s ioexp_map_cypress_7abc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+ {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+ {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+ },
+ .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */
+ {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+ {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+ {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+ {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+ {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+ },
+ .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */
+ {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+ {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+ {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+ },
+};
+
+
+
+/* ========== Private functions ==========
+ */
+int check_channel_tier_1(void);
+
+struct i2c_client *
+_get_i2c_client(struct ioexp_obj_s *self,
+ int chip_id){
+
+ struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p;
+
+ if (!(i2c_curr_p)){
+ SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__);
+ return NULL;
+ }
+ while (i2c_curr_p){
+ if ((i2c_curr_p->chip_id) == chip_id){
+ return i2c_curr_p->i2c_client_p;
+ }
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id);
+ return NULL;
+}
+
+
+static int
+_common_ioexp_update_one(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *ioexp_addr,
+ int chip_id,
+ int data_width,
+ int show_err,
+ char *caller_name) {
+ int buf = 0;
+ int err = 0;
+ int data_id = 0;
+ int r_offset = 0;
+
+ for(data_id=0; data_idread_offset[data_id];
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset);
+ /* Check error */
+ if (buf < 0) {
+ err = 1;
+ if (show_err) {
+ SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf);
+ SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n",
+ ioexp_addr->chan_id, ioexp_addr->chip_addr,
+ ioexp_addr->read_offset[data_id], caller_name);
+ }
+ continue;
+ }
+ /* Update IOEXP object */
+ self->chip_data[chip_id].data[data_id] = (uint8_t)buf;
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+static int
+common_ioexp_update_all(struct ioexp_obj_s *self,
+ int show_err,
+ char *caller_name){
+
+ int err = 0;
+ int chip_id = 0;
+ int chip_amount = self->ioexp_map_p->chip_amount;
+
+ for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]),
+ chip_id,
+ self->ioexp_map_p->data_width,
+ show_err,
+ caller_name) < 0) {
+ err = 1;
+ }
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+static int
+_common_get_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ char *func_mane){
+ uint8_t buf;
+ int err_code;
+
+ /* Get address */
+ err_code = self->fsm_4_direct(self);
+ if (err_code < 0){
+ return err_code;
+ }
+
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Get data form cache */
+ buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ return (int)(buf >> bitmap_obj_p->bit_shift & 0x01);
+}
+
+
+static int
+_common_set_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ int input_val,
+ char *func_mane){
+ int err_code, target_offset;
+ uint8_t origin_byte;
+ uint8_t modify_byte;
+
+ /* Get address */
+ err_code = self->fsm_4_direct(self);
+ if (err_code < 0){
+ return err_code;
+ }
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Prepare write date */
+ origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ switch (input_val) {
+ case 0:
+ modify_byte = origin_byte;
+ SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ case 1:
+ modify_byte = origin_byte;
+ SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ default:
+ SWPS_ERR("Input value incorrect! :%d :%d :%s\n",
+ input_val, self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADINPUT;
+ }
+ /* Setup i2c client */
+ target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset];
+ /* Write byte to chip via I2C */
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id),
+ target_offset,
+ modify_byte);
+ /* Update or bollback object */
+ if (err_code < 0){
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte;
+ SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n",
+ input_val, self->ioexp_id, func_mane, err_code);
+ return err_code;
+ }
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte;
+ return 0;
+}
+
+
+/* ========== Object public functions ==========
+ */
+int
+common_get_present(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ int UNPLUG = 1;
+ int retval = ERR_IOEXP_UNEXCPT;
+
+ retval = _common_get_bit(self,
+ &(self->ioexp_map_p->map_present[virt_offset]),
+ "common_get_present");
+ if (retval < 0) {
+ /* [Note]
+ * => Transceiver object does not need to handle IOEXP layer issues.
+ */
+ return UNPLUG;
+ }
+ return retval;
+}
+
+int
+common_get_tx_fault(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_tx_fault[virt_offset]),
+ "common_get_tx_fault");
+}
+
+int
+common_get_rxlos(struct ioexp_obj_s *self,
+ int virt_offset){
+ /* [Receiver Loss of Signal (Rx_LOS)]
+ * The post-amplification IC also includes transition detection circuitry
+ * which monitors the ac level of incoming optical signals and provides a
+ * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical
+ * input results in a low Rx_LOS output while a high Rx_LOS output indicates
+ * an unusable optical input. The Rx_LOS thresholds are factory set so that
+ * a high output indicates a definite optical fault has occurred. Rx_LOS can
+ * also be monitored via the two-wire serial interface
+ * (address A2h, byte 110, bit 1).
+ *
+ * 0: Normal
+ * 1: Abnormal
+ */
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_rxlos[virt_offset]),
+ "common_get_rxlos");
+}
+
+
+int
+common_get_tx_disable(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+ "common_get_tx_disable");
+}
+
+int
+common_get_reset(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ "common_get_reset");
+}
+
+
+int
+common_get_lpmod(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ "common_get_lpmod");
+}
+
+
+int
+common_get_modsel(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ "common_get_modsel");
+}
+
+int
+common_set_tx_disable(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+ input_val,
+ "common_set_tx_disable");
+}
+
+int
+common_set_reset(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ input_val,
+ "common_set_reset");
+}
+
+
+int
+common_set_lpmod(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ input_val,
+ "common_set_lpmod");
+}
+
+
+int
+common_set_modsel(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ input_val,
+ "common_set_modsel");
+}
+
+int
+ioexp_get_not_support(struct ioexp_obj_s *self,
+ int virt_offset){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+ioexp_set_not_support(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+/* ========== Initial functions for IO Expander ==========
+ */
+int
+common_ioexp_init(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ if (self->mode == IOEXP_MODE_DIRECT) { ///important
+ goto update_common_ioexp_init;
+ }
+ /* Setup default value to each physical IO Expander */
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ /* Get address mapping */
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("%s: IOEXP config incorrect! :%d \n",
+ __func__, chip_id);
+ return -1;
+ }
+ /* Setup default value */
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->write_offset[offset],
+ addr_p->data_default[offset]);
+ if (err_code < 0){
+ SWPS_ERR("%s: set default fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ }
+ }
+
+update_common_ioexp_init:
+ /* Check and update info to object */
+ err_code = self->update_all(self, 1, "common_ioexp_init");
+ if (err_code < 0) {
+ SWPS_ERR("%s: update_all() fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+_is_channel_ready(struct ioexp_obj_s *self){
+
+ int buf = 0;
+ int chip_id = 0; /* Use first chip which be registered */
+ int data_id = 0; /* Use first byte which be registered */
+ struct ioexp_addr_s *ioexp_addr = NULL;
+
+ ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!ioexp_addr){
+ SWPS_ERR("%s: config incorrect!\n", __func__);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id),
+ ioexp_addr->read_offset[data_id]);
+ if (buf >= 0){
+ return 1;
+ }
+ return 0;
+}
+
+int
+_ioexp_init_handler(struct ioexp_obj_s *self){
+
+ int return_val;
+
+ switch (self->mode) {
+ case IOEXP_MODE_DIRECT:
+ return_val = self->init(self);
+ if (return_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ } else {
+ self->state = STATE_IOEXP_NORMAL;
+ }
+ return return_val;
+ default:
+ break;
+ }
+ SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){
+
+ int result_val;
+ int show_err = 1;
+ char *func_mane = "common_ioexp_fsm_4_direct";
+
+ switch (self->state){
+ case STATE_IOEXP_INIT:
+ result_val = _ioexp_init_handler(self);
+ /* Exception case: terminate initial procedure */
+ if(result_val < 0){
+ /* Initial fail */
+ return result_val;
+ }
+ if(self->state == STATE_IOEXP_INIT){
+ /* Keep in INIT state, and return error */
+ return ERR_IOEXP_UNINIT;
+ }
+ /* Case: Initial done */
+ return 0;
+
+ case STATE_IOEXP_NORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ case STATE_IOEXP_ABNORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: Exception occurs :%d\n",
+ __func__, self->state);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+/* ========== Functions for Factory pattern ==========
+ */
+static struct ioexp_map_s *
+get_ioexp_map(int ioexp_type){
+ switch (ioexp_type){
+ case IOEXP_TYPE_CYPRESS_NABC:
+ return &ioexp_map_cypress_nabc;
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ return &ioexp_map_cypress_7abc;
+ default:
+ return NULL;
+ }
+}
+
+
+int
+setup_ioexp_ssize_attr(struct ioexp_obj_s *self,
+ struct ioexp_map_s *ioexp_map_p,
+ int ioexp_id,
+ int ioexp_type,
+ int run_mode){
+ switch (run_mode){
+ case IOEXP_MODE_DIRECT: /* Direct access device mode */
+ self->mode = run_mode;
+ break;
+ default:
+ SWPS_ERR("%s: non-defined run_mode:%d\n",
+ __func__, run_mode);
+ self->mode = ERR_IOEXP_UNEXCPT;
+ return ERR_IOEXP_UNEXCPT;
+ }
+ self->ioexp_id = ioexp_id;
+ self->ioexp_type = ioexp_type;
+ self->ioexp_map_p = ioexp_map_p;
+ self->state = STATE_IOEXP_INIT;
+ mutex_init(&self->lock);
+ return 0;
+}
+
+
+static int
+setup_addr_mapping(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *addr_map_p){
+ if (!addr_map_p){
+ SWPS_ERR("%s: map is null\n", __func__);
+ return -1;
+ }
+ self->ioexp_map_p->map_addr = addr_map_p;
+ return 0;
+}
+
+
+static int
+setup_ioexp_public_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+ switch (ioexp_type){
+ case IOEXP_TYPE_CYPRESS_NABC:
+ self->get_present = common_get_present;
+ self->get_tx_fault = common_get_tx_fault;
+ self->get_rxlos = common_get_rxlos;
+ self->get_tx_disable = common_get_tx_disable;
+ self->get_reset = ioexp_get_not_support;
+ self->get_lpmod = ioexp_get_not_support;
+ self->get_modsel = ioexp_get_not_support;
+ self->set_tx_disable = common_set_tx_disable;
+ self->set_reset = ioexp_set_not_support;
+ self->set_lpmod = ioexp_set_not_support;
+ self->set_modsel = ioexp_set_not_support;
+ return 0;
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ self->get_present = common_get_present;
+ self->get_tx_fault = ioexp_get_not_support;
+ self->get_rxlos = ioexp_get_not_support;
+ self->get_tx_disable = ioexp_get_not_support;
+ self->get_reset = common_get_reset;
+ self->get_lpmod = common_get_lpmod;
+ self->get_modsel = common_get_modsel;
+ self->set_tx_disable = ioexp_set_not_support;
+ self->set_reset = common_set_reset;
+ self->set_lpmod = common_set_lpmod;
+ self->set_modsel = common_set_modsel;
+ return 0;
+
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_ioexp_private_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+
+ switch (ioexp_type){
+ case IOEXP_TYPE_CYPRESS_NABC:
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ self->init = common_ioexp_init;
+ self->update_all = common_ioexp_update_all;
+ self->fsm_4_direct = common_ioexp_fsm_4_direct;
+ return 0;
+
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_i2c_client_one(struct ioexp_obj_s *self,
+ int chip_id){
+
+ char *err_msg = "ERROR";
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client = NULL;
+ struct ioexp_i2c_s *i2c_obj_p = NULL;
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+
+ int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id;
+ adap = i2c_get_adapter(chan_id);
+ if(!adap){
+ err_msg = "Can not get adap!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client){
+ err_msg = "Can not kzalloc client!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL);
+ if (!i2c_obj_p){
+ err_msg = "Can not kzalloc i2c_obj_p!";
+ goto err_ioexp_setup_i2c_2;
+ }
+ client->adapter = adap;
+ client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr;
+ i2c_obj_p->i2c_client_p = client;
+ i2c_obj_p->chip_id = chip_id;
+ i2c_obj_p->next = NULL;
+ if (!self->i2c_head_p){
+ self->i2c_head_p = i2c_obj_p;
+ } else {
+ i2c_curr_p = self->i2c_head_p;
+ while (i2c_curr_p->next){
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ i2c_curr_p->next = i2c_obj_p;
+ }
+ return 0;
+
+err_ioexp_setup_i2c_2:
+ kfree(client);
+err_ioexp_setup_i2c_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id);
+ return -1;
+}
+
+
+static int
+setup_i2c_client(struct ioexp_obj_s* self){
+
+ int result;
+ int chip_id = 0;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ result = setup_i2c_client_one(self, chip_id);
+ if (result < 0){
+ SWPS_ERR("%s fail! :%d\n", __func__, chip_id);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+setup_ioexp_config(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id);
+ return -1;
+ }
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->conf_offset[offset],
+ addr_p->conf_default[offset]);
+
+ if (err_code < 0){
+ SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code);
+ return -2;
+ }
+ }
+ }
+ return 0;
+}
+
+struct ioexp_obj_s *
+_create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_map_s* ioexp_map_p;
+ struct ioexp_obj_s* result_p;
+ struct ioexp_i2c_s *i2c_curr_p;
+ struct ioexp_i2c_s *i2c_next_p;
+
+ /* Get layout */
+ ioexp_map_p = get_ioexp_map(ioexp_type);
+ if (!ioexp_map_p){
+ SWPS_ERR("%s: Invalid ioexp_type\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare IOEXP object */
+ result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+ if (!result_p){
+ SWPS_ERR("%s: kzalloc failure!\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare static size attributes */
+ if (setup_ioexp_ssize_attr(result_p,
+ ioexp_map_p,
+ ioexp_id,
+ ioexp_type,
+ run_mode) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ /* Prepare address mapping */
+ if (setup_addr_mapping(result_p, addr_map_p) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ if (setup_i2c_client(result_p) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ /* Prepare call back functions of object */
+ if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ return result_p;
+
+err_create_ioexp_setup_i2c_fail:
+ i2c_curr_p = result_p->i2c_head_p;
+ i2c_next_p = result_p->i2c_head_p;
+ while (i2c_curr_p){
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+err_create_ioexp_setup_attr_fail:
+ kfree(result_p);
+err_create_ioexp_fail:
+ SWPS_ERR("%s: fail! :%d :%d \n",
+ __func__, ioexp_id, ioexp_type);
+ return NULL;
+}
+
+
+int
+create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_obj_s *ioexp_p = NULL;
+
+ ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type,
+ addr_map_p, run_mode);
+ if (!ioexp_p){
+ return -1;
+ }
+ if (ioexp_head_p == NULL){
+ ioexp_head_p = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+ }
+ ioexp_tail_p->next = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+}
+
+static int
+_init_ioexp_obj(struct ioexp_obj_s* self) {
+
+ char *err_msg = "ERR";
+ char *func_name = "_init_ioexp_obj";
+
+ /* Setup IOEXP configure byte */
+ if (setup_ioexp_config(self) < 0){
+ err_msg = "setup_ioexp_config fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Setup default data */
+ if (_ioexp_init_handler(self) < 0){
+ err_msg = "_ioexp_init_handler fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Update all */
+ if (self->state == STATE_IOEXP_NORMAL){
+ if (self->update_all(self, 1, func_name) < 0){
+ err_msg = "update_all() fail";
+ goto err_init_ioexp_obj;
+ }
+ }
+ return 0;
+
+err_init_ioexp_obj:
+ SWPS_DEBUG("%s: %s\n", __func__, err_msg);
+ return -1;
+}
+
+int
+init_ioexp_objs(void){
+ /* Return value:
+ * 0: Success
+ * -1: Detect topology error
+ * -2: SWPS internal error
+ */
+
+ struct ioexp_obj_s *curr_p = ioexp_head_p;
+
+ if (!curr_p) {
+ SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__);
+ return -2;
+ }
+ while (curr_p) {
+ if (_init_ioexp_obj(curr_p) < 0) {
+ SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__);
+ return -1;
+ }
+ curr_p = curr_p->next;
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+ return 0;
+}
+
+void
+clean_ioexp_objs(void){
+
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+ struct ioexp_i2c_s *i2c_next_p = NULL;
+ struct ioexp_obj_s *ioexp_next_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ if (ioexp_head_p == NULL){
+ ioexp_tail_p = NULL;
+ return;
+ }
+ while(ioexp_curr_p){
+ ioexp_next_p = ioexp_curr_p->next;
+ i2c_curr_p = ioexp_curr_p->i2c_head_p;
+ while (i2c_curr_p) {
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+ kfree(ioexp_curr_p);
+ ioexp_curr_p = ioexp_next_p;
+ }
+ ioexp_tail_p = NULL;
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+struct ioexp_obj_s *
+get_ioexp_obj(int ioexp_id){
+
+ struct ioexp_obj_s *result_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while(ioexp_curr_p){
+ if (ioexp_curr_p->ioexp_id == ioexp_id){
+ result_p = ioexp_curr_p;
+ break;
+ }
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return result_p;
+}
+int
+check_channel_tier_1(void) {
+
+ if ( (!_is_channel_ready(ioexp_head_p)) &&
+ (!_is_channel_ready(ioexp_tail_p)) ){
+ return -1;
+ }
+ return 0;
+}
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h
new file mode 100644
index 000000000000..a5541617dd05
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h
@@ -0,0 +1,143 @@
+#ifndef IO_EXPANDER_H
+#define IO_EXPANDER_H
+
+#include
+
+/* IOEXP type define (QSFP series) */
+#define IOEXP_TYPE_CYPRESS_NABC (10102)
+#define IOEXP_TYPE_CYPRESS_7ABC (10207)
+
+/* IOEXP mode define */
+#define IOEXP_MODE_DIRECT (19001)
+
+/* IOEXP state define */
+#define STATE_IOEXP_NORMAL (0)
+#define STATE_IOEXP_INIT (-1)
+#define STATE_IOEXP_ABNORMAL (-2)
+
+/* IOEXP error code define */
+#define ERR_IOEXP_NOTSUPPORT (-100)
+#define ERR_IOEXP_UNINIT (-101)
+#define ERR_IOEXP_BADCONF (-102)
+#define ERR_IOEXP_BADINPUT (-105)
+#define ERR_IOEXP_UNEXCPT (-199)
+
+
+#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
+#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
+#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args)
+
+#ifdef DEBUG_SWPS
+# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args)
+#else
+# define SWPS_DEBUG(fmt, args...)
+#endif
+
+
+struct ioexp_addr_s {
+ int chan_id;
+ int chip_addr;
+ int read_offset[8];
+ int write_offset[8];
+ int conf_offset[8];
+ uint8_t data_default[8];
+ uint8_t conf_default[8];
+};
+
+struct ioexp_i2c_s {
+ int chip_id;
+ struct i2c_client *i2c_client_p;
+ struct ioexp_i2c_s *next;
+};
+
+
+struct ioexp_bitmap_s {
+ int chip_id; /* IOEXP chip id */
+ int ioexp_voffset; /* IOEXP virtual offset */
+ int bit_shift;
+};
+
+struct ioexp_map_s {
+ int chip_amount; /* Number of chips that IOEXP object content */
+ int data_width; /* Number of (Read/Write/Config) bytes */
+ struct ioexp_addr_s *map_addr; /* Chip address info */
+ struct ioexp_bitmap_s map_present[8]; /* IOEXP for SFP / QSFP */
+ struct ioexp_bitmap_s map_tx_disable[8]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_tx_fault[8]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_rxlos[8]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_reset[8]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_lpmod[8]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_modsel[8]; /* IOEXP for QSFP */
+};
+
+struct ioexp_data_s {
+ uint8_t data[8];
+};
+
+struct ioexp_obj_s {
+
+ /* ============================
+ * Object public property
+ * ============================
+ */
+ int ioexp_id;
+ int ioexp_type;
+
+ /* ============================
+ * Object private property
+ * ============================
+ */
+ struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
+ struct ioexp_map_s *ioexp_map_p;
+ struct ioexp_obj_s *next;
+ struct ioexp_i2c_s *i2c_head_p;
+ struct mutex lock;
+ int mode;
+ int state;
+
+ /* ===========================================
+ * Object public functions
+ * ===========================================
+ */
+ int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
+ int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+
+ /* ===========================================
+ * Object private functions
+ * ===========================================
+ */
+ int (*init)(struct ioexp_obj_s *self);
+ int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
+ int (*fsm_4_direct)(struct ioexp_obj_s* self);
+};
+
+
+struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
+int create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode);
+int init_ioexp_objs(void);
+void clean_ioexp_objs(void);
+
+int check_channel_tier_1(void);
+
+/* Macro for bit control */
+#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift)))
+#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
+
+
+#endif /* IO_EXPANDER_H */
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c
new file mode 100644
index 000000000000..368e412b19e2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c
@@ -0,0 +1,906 @@
+#include
+#include
+#include
+#include
+#include "io_expander.h"
+#include "transceiver.h"
+
+
+/* ========== Register EEPROM address mapping ==========
+ */
+struct eeprom_map_s eeprom_map_sfp = {
+ .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1,
+ .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1,
+ .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1,
+};
+
+struct eeprom_map_s eeprom_map_qsfp = {
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+};
+
+struct eeprom_map_s eeprom_map_qsfp28 = {
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+};
+
+
+/* ========== Utility Functions ==========
+ */
+void
+alarm_msg_2_user(struct transvr_obj_s *self,
+ char *emsg) {
+
+ SWPS_ERR("%s on %s.\n", emsg, self->swp_name);
+}
+
+
+/* ========== Private functions ==========
+ */
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self);
+
+static void
+_transvr_clean_retry(struct transvr_obj_s *self) {
+ self->retry = 0;
+}
+
+
+static int
+_transvr_handle_retry(struct transvr_obj_s *self, int retry) {
+ /* Return: 0: keep retry
+ * -1: stop retry
+ */
+ if (self->retry == 0) {
+ self->retry = retry;
+ }
+ self->retry -= 1;
+ if (self->retry <= 0) {
+ _transvr_clean_retry(self);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_common_setup_page(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ int show_e) {
+ /* return:
+ * 0 : OK
+ * -1 : EEPROM settings incorrect
+ * -2 : I2C R/W failure
+ * -3 : Undefined case
+ */
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Check */
+ if ((addr < 0) || (offset < 0) || (len < 0)) {
+ emsg = "EEPROM settings incorrect";
+ retval = -1;
+ goto err_common_setup_page;
+ }
+ /* Case1: continue access */
+ if ((self->i2c_client_p->addr == addr) &&
+ (self->curr_page == page)) {
+ return 0;
+ }
+ self->i2c_client_p->addr = addr;
+ /* Case2: select lower page */
+ if (page == -1) {
+ self->curr_page = page;
+ return 0;
+ }
+ /* Case3: select upper page */
+ if (page >= 0) {
+ goto upper_common_setup_page;
+ }
+ /* Unexpected case */
+ show_e = 1;
+ emsg = "Unexpected case";
+ retval = -3;
+ goto err_common_setup_page;
+
+upper_common_setup_page:
+ if (i2c_smbus_write_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_PAGE_SELECT_OFFSET,
+ page) < 0) {
+ emsg = "I2C R/W failure";
+ retval = -2;
+ goto err_common_setup_page;
+ }
+ self->curr_page = page;
+ mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY);
+ return 0;
+
+err_common_setup_page:
+ if (show_e) {
+ SWPS_INFO("%s: %s", __func__, emsg);
+ SWPS_INFO("%s: :0x%02x :%d :%d :%d\n",
+ __func__, addr, page, offset, len);
+ }
+ return retval;
+}
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+is_plugged(struct transvr_obj_s *self){
+
+ int limit = 63;
+ int present = DEBUG_TRANSVR_INT_VAL;
+ char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+ struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ snprintf(emsg, limit, "ioexp_p is null!");
+ goto err_is_plugged_1;
+ }
+ present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset);
+ switch (present){
+ case 0:
+ return 1;
+ case 1:
+ return 0;
+ case ERR_IOEXP_UNINIT:
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ default:
+ if (ioexp_p->state == STATE_IOEXP_INIT){
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ }
+ break;
+ }
+ SWPS_INFO("%s: Exception case! :%d :%d\n",
+ __func__, present, ioexp_p->state);
+ return 0;
+
+err_is_plugged_1:
+ SWPS_DEBUG("%s: %s\n", __func__, emsg);
+ return 0;
+}
+
+
+static int
+detect_transvr_type(struct transvr_obj_s* self){
+
+ int type = TRANSVR_TYPE_ERROR;
+
+ self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+ type = i2c_smbus_read_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_COMID_OFFSET);
+
+ /* Case: 1. Wait transceiver I2C module.
+ * 2. Transceiver I2C module failure.
+ * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there
+ * are exist some case that we need to wait transceiver.
+ * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than
+ * state machine will keep trace with it.
+ * 2. There exist some I2C failure case we need to handle. Such as user
+ * insert the failure transceiver, or any reason cause it abnormal.
+ */
+ if (type < 0){
+ switch (type) {
+ case -EIO:
+ SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n",
+ __func__, self->swp_name);
+ return TRANSVR_TYPE_UNPLUGGED;
+ case -ENXIO:
+ SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n",
+ __func__, self->swp_name);
+ return TRANSVR_TYPE_UNPLUGGED;
+ default:
+ break;
+ }
+ SWPS_INFO("%s: %s unexpected smbus return:%d \n",
+ __func__, self->swp_name, type);
+ return TRANSVR_TYPE_ERROR;
+ }
+ /* Identify valid transceiver type */
+ switch (type){
+ case TRANSVR_TYPE_SFP:
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ case TRANSVR_TYPE_QSFP_28:
+ break;
+ case TRANSVR_TYPE_UNKNOW_1:
+ case TRANSVR_TYPE_UNKNOW_2:
+ type = TRANSVR_TYPE_UNKNOW_2;
+ break;
+ default:
+ SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type);
+ type = TRANSVR_TYPE_ERROR;
+ break;
+ }
+ return type;
+}
+
+
+static int
+detect_transvr_state(struct transvr_obj_s *self,
+ int result[2]){
+ /* [return] [result-0] [result-1]
+ * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE
+ * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED
+ * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR
+ * 0 STATE_TRANSVR_INIT /
+ * 0 STATE_TRANSVR_SWAPPED
+ * 0 STATE_TRANSVR_CONNECTED
+ * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR
+ * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR